Commit 5a26235c authored by Edward Wang's avatar Edward Wang Committed by Rafaël Carré

Use MRLs and libvlc_media_new_location everywhere

Signed-off-by: Rafaël Carré's avatarRafaël Carré <funman@videolan.org>
parent 2fcdf337
......@@ -19,6 +19,7 @@ else
CPP_STATIC=$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/libs/$(ARCH)/libgnustl_static.a
endif
LOCAL_CFLAGS := -std=gnu99
LOCAL_LDLIBS := -L$(VLC_CONTRIB)/lib \
$(VLC_MODULES) \
$(VLC_BUILD_DIR)/lib/.libs/libvlc.a \
......
......@@ -22,6 +22,8 @@
#include <pthread.h>
#include <vlc/vlc.h>
#include <vlc_common.h>
#include <vlc_url.h>
#include <jni.h>
......@@ -34,13 +36,13 @@
#define LOG_TAG "VLC/JNI/main"
#include "log.h"
libvlc_media_t *new_media(jint instance, JNIEnv *env, jobject thiz, jstring filePath)
libvlc_media_t *new_media(jint instance, JNIEnv *env, jobject thiz, jstring fileLocation)
{
libvlc_instance_t *libvlc = (libvlc_instance_t*)instance;
jboolean isCopy;
const char *psz_path = (*env)->GetStringUTFChars(env, filePath, &isCopy);
libvlc_media_t *p_md = libvlc_media_new_path(libvlc, psz_path);
(*env)->ReleaseStringUTFChars(env, filePath, psz_path);
const char *psz_location = (*env)->GetStringUTFChars(env, fileLocation, &isCopy);
libvlc_media_t *p_md = libvlc_media_new_location(libvlc, psz_location);
(*env)->ReleaseStringUTFChars(env, fileLocation, psz_location);
if (!p_md)
return NULL;
......@@ -244,6 +246,20 @@ void Java_org_videolan_vlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
LOGI("LibVLC initialized: %p", instance);
}
jstring Java_org_videolan_vlc_LibVLC_nativeToURI(JNIEnv *env, jobject thiz, jstring path)
{
jboolean isCopy;
/* Get C string */
const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);
/* Convert the path to URI */
char* psz_location = make_URI(psz_path, "file");
/* Box into jstring */
jstring t = (*env)->NewStringUTF(env, psz_location);
/* Clean up */
(*env)->ReleaseStringUTFChars(env, path, psz_path);
free(psz_location);
return t;
}
void Java_org_videolan_vlc_LibVLC_nativeDestroy(JNIEnv *env, jobject thiz)
{
......@@ -443,10 +459,10 @@ void Java_org_videolan_vlc_LibVLC_readMedia(JNIEnv *env, jobject thiz,
}
jboolean Java_org_videolan_vlc_LibVLC_hasVideoTrack(JNIEnv *env, jobject thiz,
jint i_instance, jstring filePath)
jint i_instance, jstring fileLocation)
{
/* Create a new item and assign it to the media player. */
libvlc_media_t *p_m = new_media(i_instance, env, thiz, filePath);
libvlc_media_t *p_m = new_media(i_instance, env, thiz, fileLocation);
if (p_m == NULL)
{
LOGE("Couldn't create the media!");
......@@ -553,8 +569,8 @@ static void length_changed_callback(const libvlc_event_t *ev, void *data)
pthread_mutex_unlock(&monitor->doneMutex);
}
jlong Java_org_videolan_vlc_LibVLC_getLengthFromFile(JNIEnv *env, jobject thiz,
jint i_instance, jstring filePath)
jlong Java_org_videolan_vlc_LibVLC_getLengthFromLocation(JNIEnv *env, jobject thiz,
jint i_instance, jstring fileLocation)
{
jlong length = 0;
struct length_change_monitor *monitor;
......@@ -568,7 +584,7 @@ jlong Java_org_videolan_vlc_LibVLC_getLengthFromFile(JNIEnv *env, jobject thiz,
monitor->length_changed = false;
/* Create a new item and assign it to the media player. */
libvlc_media_t *m = new_media(i_instance, env, thiz, filePath);
libvlc_media_t *m = new_media(i_instance, env, thiz, fileLocation);
if (m == NULL)
{
LOGE("Couldn't create the media to play!");
......
......@@ -292,7 +292,7 @@ public class AudioService extends Service {
return;
}
}
mLibVLC.readMedia(mCurrentMedia.getPath());
mLibVLC.readMedia(mCurrentMedia.getLocation());
mHandler.sendEmptyMessage(SHOW_PROGRESS);
showNotification();
updateWidget(this);
......@@ -306,7 +306,7 @@ public class AudioService extends Service {
mCurrentMedia = mMediaList.get(index - 1);
else
return;
mLibVLC.readMedia(mCurrentMedia.getPath());
mLibVLC.readMedia(mCurrentMedia.getLocation());
mHandler.sendEmptyMessage(SHOW_PROGRESS);
showNotification();
updateWidget(this);
......@@ -344,7 +344,7 @@ public class AudioService extends Service {
if (b != null)
return b;
}
File f = new File(mCurrentMedia.getPath());
File f = new File(mCurrentMedia.getLocation());
for (File s : f.getParentFile().listFiles()) {
if (s.getAbsolutePath().endsWith("png") ||
s.getAbsolutePath().endsWith("jpg"))
......@@ -358,8 +358,8 @@ public class AudioService extends Service {
private IAudioService.Stub mInterface = new IAudioService.Stub() {
@Override
public String getCurrentMediaPath() throws RemoteException {
return mCurrentMedia.getPath();
public String getCurrentMediaLocation() throws RemoteException {
return mCurrentMedia.getLocation();
}
@Override
......@@ -478,7 +478,7 @@ public class AudioService extends Service {
}
if (mCurrentMedia != null)
mLibVLC.readMedia(mCurrentMedia.getPath());
mLibVLC.readMedia(mCurrentMedia.getLocation());
showNotification();
}
......@@ -501,14 +501,14 @@ public class AudioService extends Service {
ArrayList<String> medias = new ArrayList<String>();
for (int i = 0; i < mMediaList.size(); i++) {
Media item = mMediaList.get(i);
medias.add(item.getPath());
medias.add(item.getLocation());
}
return medias;
}
public String getItem() {
return mCurrentMedia != null
? mCurrentMedia.getPath()
? mCurrentMedia.getLocation()
: null;
}
......
......@@ -51,7 +51,7 @@ public class DatabaseManager {
private final String DIR_ROW_PATH = "path";
private final String MEDIA_TABLE_NAME = "media_table";
private final String MEDIA_PATH = "path";
private final String MEDIA_LOCATION = "location";
private final String MEDIA_TIME = "time";
private final String MEDIA_LENGTH = "length";
private final String MEDIA_TYPE = "type";
......@@ -115,7 +115,7 @@ public class DatabaseManager {
String createMediaTabelQuery = "CREATE TABLE IF NOT EXISTS "
+ MEDIA_TABLE_NAME + " ("
+ MEDIA_PATH + " TEXT PRIMARY KEY NOT NULL, "
+ MEDIA_LOCATION + " TEXT PRIMARY KEY NOT NULL, "
+ MEDIA_TIME + " INTEGER, "
+ MEDIA_LENGTH + " INTEGER, "
+ MEDIA_TYPE + " INTEGER, "
......@@ -219,7 +219,7 @@ public class DatabaseManager {
ContentValues values = new ContentValues();
values.put(MEDIA_PATH, media.getPath());
values.put(MEDIA_LOCATION, media.getLocation());
values.put(MEDIA_TIME, media.getTime());
values.put(MEDIA_LENGTH, media.getLength());
values.put(MEDIA_TYPE, media.getType());
......@@ -259,7 +259,7 @@ public class DatabaseManager {
cursor = mDb.query(
MEDIA_TABLE_NAME,
new String[] { MEDIA_PATH },
new String[] { MEDIA_LOCATION },
null, null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
......@@ -293,7 +293,7 @@ public class DatabaseManager {
MEDIA_ARTIST, //5 string
MEDIA_GENRE, //6 string
MEDIA_ALBUM, //7 string
MEDIA_PATH, //8 string
MEDIA_LOCATION, //8 string
MEDIA_TABLE_NAME,
CHUNK_SIZE,
chunk_count * CHUNK_SIZE), null);
......@@ -304,13 +304,15 @@ public class DatabaseManager {
if (blob != null) {
picture = BitmapFactory.decodeByteArray(blob, 0, blob.length);
}
Media media = new Media(context, new File(cursor.getString(8)), cursor.getLong(0),
cursor.getLong(1), cursor.getInt(2),
String location = cursor.getString(8);
File file = Util.URItoFile(location);
Media media = new Media(context, location, file.getName().substring(0, file.getName().lastIndexOf('.')),
cursor.getLong(0), cursor.getLong(1), cursor.getInt(2),
picture, cursor.getString(4),
cursor.getString(5), cursor.getString(6),
cursor.getString(7));
medias.put(media.getPath(), media);
medias.put(media.getLocation(), media);
picture = null;
count++;
} while (cursor.moveToNext());
......@@ -323,7 +325,7 @@ public class DatabaseManager {
return medias;
}
public synchronized Media getMedia(Context context, String path) {
public synchronized Media getMedia(Context context, String location) {
Cursor cursor;
Media media = null;
......@@ -342,8 +344,8 @@ public class DatabaseManager {
MEDIA_GENRE, //6 string
MEDIA_ALBUM //7 string
},
MEDIA_PATH + "=?",
new String[] { path },
MEDIA_LOCATION + "=?",
new String[] { location },
null, null, null);
if (cursor.moveToFirst()) {
......@@ -351,9 +353,9 @@ public class DatabaseManager {
if (blob != null) {
picture = BitmapFactory.decodeByteArray(blob, 0, blob.length);
}
media = new Media(context, new File(path), cursor.getLong(0),
cursor.getLong(1), cursor.getInt(2),
File file = Util.URItoFile(location);
media = new Media(context, location, file.getName().substring(0, file.getName().lastIndexOf('.')),
cursor.getLong(0), cursor.getLong(1), cursor.getInt(2),
picture, cursor.getString(4),
cursor.getString(5), cursor.getString(6),
cursor.getString(7));
......@@ -362,11 +364,11 @@ public class DatabaseManager {
return media;
}
public synchronized void removeMedia(String path) {
mDb.delete(MEDIA_TABLE_NAME, MEDIA_PATH + "=?", new String[] { path });
public synchronized void removeMedia(String location) {
mDb.delete(MEDIA_TABLE_NAME, MEDIA_LOCATION + "=?", new String[] { location });
}
public synchronized void updateMedia(String path, mediaColumn col,
public synchronized void updateMedia(String location, mediaColumn col,
Object object) {
ContentValues values = new ContentValues();
switch (col) {
......@@ -379,7 +381,7 @@ public class DatabaseManager {
default:
return;
}
mDb.update(MEDIA_TABLE_NAME, values, MEDIA_PATH + "=?", new String[] { path });
mDb.update(MEDIA_TABLE_NAME, values, MEDIA_LOCATION + "=?", new String[] { location });
}
/**
......
......@@ -204,22 +204,22 @@ public class LibVLC {
/**
* Get a media thumbnail.
*/
public byte[] getThumbnail(String filePath, int i_width, int i_height) {
return getThumbnail(mLibVlcInstance, filePath, i_width, i_height);
public byte[] getThumbnail(String mrl, int i_width, int i_height) {
return getThumbnail(mLibVlcInstance, mrl, i_width, i_height);
}
/**
* Return true if there is a video track in the file
*/
public boolean hasVideoTrack(String filePath) {
return hasVideoTrack(mLibVlcInstance, filePath);
public boolean hasVideoTrack(String mrl) {
return hasVideoTrack(mLibVlcInstance, mrl);
}
/**
* Return the length of the stream, in milliseconds
*/
public long getLengthFromFile(String filePath) {
return getLengthFromFile(mLibVlcInstance, filePath);
public long getLengthFromLocation(String mrl) {
return getLengthFromLocation(mLibVlcInstance, mrl);
}
/**
......@@ -335,12 +335,12 @@ public class LibVLC {
* Get a media thumbnail.
* @return a bytearray with the RGBA thumbnail data inside.
*/
private native byte[] getThumbnail(int instance, String filePath, int i_width, int i_height);
private native byte[] getThumbnail(int instance, String mrl, int i_width, int i_height);
/**
* Return true if there is a video track in the file
*/
private native boolean hasVideoTrack(int instance, String filePath);
private native boolean hasVideoTrack(int instance, String mrl);
private native String[] readMediaMeta(int instance, String mrl);
......@@ -358,10 +358,12 @@ public class LibVLC {
public native int getSpuTracksCount();
public native String nativeToURI(String path);
/**
* Return the length of the stream, in milliseconds
*/
private native long getLengthFromFile(int instance, String filePath);
private native long getLengthFromLocation(int instance, String mrl);
private native void setEventManager(EventManager eventManager);
......
......@@ -21,6 +21,8 @@
package org.videolan.vlc;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import android.content.Context;
import android.graphics.Bitmap;
......@@ -62,7 +64,8 @@ public class Media implements Comparable<Media> {
private String mEncodedBy;
private String mTrackID;
private File mFile;
private String mLocation;
private String mFilename;
private long mTime = 0;
private long mLength = 0;
private int mType;
......@@ -71,19 +74,32 @@ public class Media implements Comparable<Media> {
private Bitmap mPicture;
/**
* Create an new Media
* @param file: path on the local storage
* Create a new Media
* @param context Application context of the caller
* @param MRL the file's MRL (media resource locator)
* @param addToDb Should it be added to the file database?
*/
public Media(Context context, File file) {
this.mFile = file;
public Media(Context context, String MRL, Boolean addToDb) {
mLocation = MRL;
try {
URL urlobj = new URL(MRL);
mFilename = urlobj.getFile().substring(urlobj.getFile().lastIndexOf('/') + 1);
/* empty filenames are awkward */
if(mFilename.equals("")) {
mFilename = urlobj.getHost();
}
} catch (MalformedURLException e1) {
mFilename = "";
}
LibVLC mLibVlc = null;
try {
mLibVlc = LibVLC.getInstance();
mType = (mLibVlc.hasVideoTrack(file.getPath())) ? TYPE_VIDEO : TYPE_AUDIO;
mLength = mLibVlc.getLengthFromFile(file.getPath());
mType = (mLibVlc.hasVideoTrack(mLocation)) ? TYPE_VIDEO : TYPE_AUDIO;
mLength = mLibVlc.getLengthFromLocation(mLocation);
String[] array = mLibVlc.readMediaMeta(file.getPath());
String[] array = mLibVlc.readMediaMeta(mLocation);
int i;
for (i = 0; i < array.length; i++) {
......@@ -108,14 +124,28 @@ public class Media implements Comparable<Media> {
e.printStackTrace();
}
// Add this item to database
DatabaseManager db = DatabaseManager.getInstance(context);
db.addMedia(this);
if(addToDb) {
// Add this item to database
DatabaseManager db = DatabaseManager.getInstance(context);
db.addMedia(this);
}
}
public Media(Context context, File file, long time, long length, int type,
/**
* Create from file
*
* @param context Context of the caller
* @param file File object of the file to be added
*/
public Media(Context context, File file) {
this(context, Util.PathToURI(file.getPath()), true);
mFilename = file.getName().substring(0, file.getName().lastIndexOf('.'));
}
public Media(Context context, String location, String filename, long time, long length, int type,
Bitmap picture, String title, String artist, String genre, String album) {
mFile = file;
mLocation = location;
mFilename = filename;
mTime = time;
mLength = length;
mType = type;
......@@ -135,12 +165,8 @@ public class Media implements Comparable<Media> {
another.getTitle().toUpperCase());
}
public File getFile() {
return mFile;
}
public String getPath() {
return mFile.getPath();
public String getLocation() {
return mLocation;
}
public void updateMeta() {
......@@ -148,7 +174,7 @@ public class Media implements Comparable<Media> {
}
public String getFileName() {
return mFile.getName().substring(0, mFile.getName().lastIndexOf('.'));
return mFilename;
}
public long getTime() {
......@@ -182,17 +208,17 @@ public class Media implements Comparable<Media> {
public void setPicture(Context context, Bitmap p) {
Log.d(TAG, "Set new picture for " + getTitle());
DatabaseManager.getInstance(context).updateMedia(
mFile.getPath(),
mLocation,
DatabaseManager.mediaColumn.MEDIA_PICTURE,
p);
mPicture = p;
}
public String getTitle() {
if (mTitle == null)
return mFile.getName().substring(0, mFile.getName().lastIndexOf('.'));
else
if(mTitle != null)
return mTitle;
else
return mFilename;
}
public String getArtist() {
......
......@@ -132,10 +132,10 @@ public class MediaLibrary {
return mItemList;
}
public Media getMediaItem(String path) {
public Media getMediaItem(String location) {
for (int i = 0; i < mItemList.size(); i++) {
Media item = mItemList.get(i);
if (item.getPath().equals(path)) {
if (item.getLocation().equals(location)) {
return item;
}
}
......@@ -183,9 +183,9 @@ public class MediaLibrary {
HashMap<String, Media> existingMedias = mDBManager.getMedias(mContext);
// list of all added files
HashSet<File> addedFiles = new HashSet<File>();
HashSet<String> addedLocations = new HashSet<String>();
// clear all old item
// clear all old items
mItemList.clear();
MediaItemFilter mediaFileFilter = new MediaItemFilter();
......@@ -221,18 +221,17 @@ public class MediaLibrary {
File file = f[i];
if (file.isFile()) {
MainActivity.sendTextInfo(mContext, file.getName(), count, total);
count++;
if (existingMedias.containsKey(file.getPath())) {
String fileURI = Util.PathToURI(file.getPath());
if (existingMedias.containsKey(fileURI)) {
/** only add file if it is not already in the
* list. eg. if user select an subfolder as well
*/
if (!addedFiles.contains(file)) {
if (!addedLocations.contains(fileURI)) {
// get existing media item from database
mItemList.add(existingMedias.get(file.getPath()));
addedFiles.add(file);
mItemList.add(existingMedias.get(fileURI));
addedLocations.add(fileURI);
}
} else {
// create new media item
......@@ -252,11 +251,11 @@ public class MediaLibrary {
}
// remove file from database
for (File file : addedFiles) {
existingMedias.remove(file.getPath());
for (String fileURI : addedLocations) {
existingMedias.remove(fileURI);
}
for (String path : existingMedias.keySet()) {
mDBManager.removeMedia(path);
for (String existingMedia : existingMedias.keySet()) {
mDBManager.removeMedia(existingMedia);
}
// hide progressbar in header
......
......@@ -122,7 +122,7 @@ public class ThumbnailerManager extends Thread {
// Get the thumbnail.
Bitmap thumbnail = Bitmap.createBitmap(width, height, Config.ARGB_8888);
//Log.i(TAG, "create new bitmap for: " + item.getName());
byte[] b = mLibVlc.getThumbnail(item.getPath(), width, height);
byte[] b = mLibVlc.getThumbnail(item.getLocation(), width, height);
if (b == null) // We were not able to create a thumbnail for this item.
continue;
......
......@@ -20,6 +20,7 @@
package org.videolan.vlc;
import java.io.File;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
......@@ -39,6 +40,20 @@ public class Util {
toaster(context, stringId, Toast.LENGTH_SHORT);
}
public static File URItoFile(String URI) {
return new File(URI.replace("file://", "file:"));
}
public static String PathToURI(String path) {
String URI;
try {
URI = LibVLC.getInstance().nativeToURI(path);
} catch (LibVlcException e) {
URI = "";
}
return URI;
}
/**
* Convert time to a string
* @param millis e.g.time/length from file
......
......@@ -122,9 +122,9 @@ public class SearchActivity extends ListActivity {
continue;
boolean add = true;
String name = item.getTitle().toLowerCase();
String path = item.getPath().toLowerCase();
String MRL = item.getLocation().toLowerCase();
for (int k = 0; k < keys.length; k++) {
if (!(name.contains(keys[k].toLowerCase()) || path.contains(keys[k].toLowerCase()))) {
if (!(name.contains(keys[k].toLowerCase()) || MRL.contains(keys[k].toLowerCase()))) {
add = false;
break;
}
......@@ -252,15 +252,15 @@ public class SearchActivity extends ListActivity {
Intent intent;
if (item.getType() == Media.TYPE_VIDEO) {
intent = new Intent(this, VideoPlayerActivity.class);
intent.putExtra("filePath", item.getPath());
intent.putExtra("itemLocation", item.getLocation());
} else {
ArrayList<String> arr = new ArrayList<String>();
for (int i = 0; i < getListAdapter().getCount(); i++) {
Media audioItem = (Media) getListAdapter().getItem(i);
if (audioItem.getType() == Media.TYPE_AUDIO)
arr.add(audioItem.getPath());
arr.add(audioItem.getLocation());
}
AudioServiceController.getInstance().load(arr, arr.indexOf(item.getPath()));
AudioServiceController.getInstance().load(arr, arr.indexOf(item.getLocation()));