/*****************************************************************************
* BrowserActivity.java
*****************************************************************************
* Copyright © 2011-2012 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.vlc.gui;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import java.util.Stack;
import org.videolan.libvlc.Media;
import org.videolan.vlc.MediaDatabase;
import org.videolan.vlc.Util;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.InputType;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.EditText;
import android.widget.ListView;
import org.tribler.triblersvod.gui.R;
public class BrowserActivity extends ListActivity {
public final static String TAG = "VLC/BrowserActivity";
/**
* TODO:
*/
private BrowserAdapter mAdapter;
private File mCurrentDir;
private final Stack<ScrollState> mScrollStates = new Stack<ScrollState>();
private String mRoots[];
private class ScrollState {
public ScrollState(int index, int top) {
this.index = index;
this.top = top;
}
int index;
int top;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.browser);
mAdapter = new BrowserAdapter(this);
setListAdapter(mAdapter);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
filter.addAction(Intent.ACTION_MEDIA_EJECT);
filter.addDataScheme("file");
registerReceiver(messageReceiver, filter);
refreshRoots();
openStorageDevices(mRoots);
registerForContextMenu(getListView());
}
private void refreshRoots() {
ArrayList<String> list = new ArrayList<String>();
list.addAll(Arrays.asList(Util.getStorageDirectories()));
list.addAll(Arrays.asList(Util.getCustomDirectories()));
mRoots = list.toArray(new String[list.size()]);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(messageReceiver);
mAdapter.clear();
mScrollStates.clear();
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
int position = ((AdapterContextMenuInfo)menuInfo).position;
final File item = mAdapter.getItem(position);
if (mCurrentDir != null
|| item.getPath().equals(BrowserAdapter.ADD_ITEM_PATH)
|| Arrays.asList(Util.getStorageDirectories()).contains(
item.getPath())) {
return;
}
MenuItem delete = menu.add(R.string.remove_custom_path);
delete.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem arg0) {
// remove any checkmarks of the custom item
final MediaDatabase dbManager = MediaDatabase.getInstance(BrowserActivity.this);
for(File f : dbManager.getMediaDirs()) {
if(f.getPath().startsWith(item.getPath()))
dbManager.removeDir(f.getPath());
}
Util.removeCustomDirectory(item.getPath());
refresh();
return true;
}
});
}
private void openStorageDevices(String roots[]) {
mCurrentDir = null;
mAdapter.clear();
for (String s : roots) {
File f = new File(s);
if (f.exists())
mAdapter.add(f);
}
mAdapter.add(new File(BrowserAdapter.ADD_ITEM_PATH));
mAdapter.sort();
// set scroll position to top
getListView().setSelection(0);
}
private void openDir(File file) {
if(file == null || !file.exists() || file.getPath() == null
|| file.getPath().equals(BrowserAdapter.ADD_ITEM_PATH))
return;
mAdapter.clear();
mCurrentDir = file;
File[] files = file.listFiles(new DirFilter());
/* If no sub-directories or I/O error don't crash */
if(files == null || files.length < 1) {
Util.toaster(this, R.string.nosubdirectory);
this.finish();
return;
}
for (int i = 0; i < files.length; i++) {
mAdapter.add(files[i]);
}
mAdapter.sort();
// set scroll position to top
getListView().setSelection(0);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
File file = mAdapter.getItem(position);
if(file.getPath().equals(BrowserAdapter.ADD_ITEM_PATH)) {
AlertDialog.Builder b = new AlertDialog.Builder(this);
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
b.setTitle(R.string.add_custom_path);
b.setMessage(R.string.add_custom_path_description);
b.setView(input);
b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface x, int y) {return;}
});
b.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Util.addCustomDirectory(input.getText().toString());
refresh();
}
});
b.show();
return;
}
File[] files = file.listFiles(new DirFilter());
if (files != null && files.length > 0) {
// store scroll state
int index = l.getFirstVisiblePosition();
int top = l.getChildAt(0).getTop();
mScrollStates.push(new ScrollState(index, top));
openDir(file);
} else {
Util.toaster(this, R.string.nosubdirectory);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mCurrentDir == null) {
// We're on the list of storage devices
return super.onKeyDown(keyCode, event);
}
// Check if we are on one of the root
boolean isRoot = false;
for (String root: mRoots) {
if (mCurrentDir.getPath().equals(root)) {
isRoot = true;
break;
}
}
if (isRoot) {
openStorageDevices(mRoots);
return true;
} else {
openDir(mCurrentDir.getParentFile());
// restore scroll state
if (mScrollStates.size() > 0) {
ScrollState ss = mScrollStates.pop();
getListView().setSelectionFromTop(ss.index, ss.top);
return true;
}
}
}
return super.onKeyDown(keyCode, event);
}
public void refresh() {
if (mCurrentDir == null) {
refreshRoots();
openStorageDevices(mRoots);
} else {
openDir(mCurrentDir);
}
mAdapter.notifyDataSetChanged();
}
private final BroadcastReceiver messageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase(Intent.ACTION_MEDIA_MOUNTED) ||
action.equalsIgnoreCase(Intent.ACTION_MEDIA_UNMOUNTED) ||
action.equalsIgnoreCase(Intent.ACTION_MEDIA_REMOVED) ||
action.equalsIgnoreCase(Intent.ACTION_MEDIA_EJECT)) {
refresh();
}
}
};
/**
* Filter: accept only directories
*/
private class DirFilter implements FileFilter {
@Override
public boolean accept(File f) {
return f.isDirectory() && !Media.FOLDER_BLACKLIST.contains(f.getPath().toLowerCase(Locale.ENGLISH));
}
}
}