[Android] [PATCH] Add open stream feature in UI
Rafaël Carré
funman at videolan.org
Sun Mar 11 01:13:08 CET 2012
Hi,
Le 10/03/2012 18:47, Edward Wang a écrit :
> ---
> vlc-android/res/menu/media_library.xml | 4 +
> vlc-android/res/values/strings.xml | 1 +
> vlc-android/src/org/videolan/vlc/AudioService.java | 12 ++-
> vlc-android/src/org/videolan/vlc/Media.java | 82 +++++++++++++++++++-
> .../src/org/videolan/vlc/gui/MainActivity.java | 28 +++++++
> .../vlc/gui/audio/AudioBrowserActivity.java | 4 +-
> 6 files changed, 122 insertions(+), 9 deletions(-)
>
> diff --git a/vlc-android/res/menu/media_library.xml b/vlc-android/res/menu/media_library.xml
> index 06c0166..bc2ee09 100644
> --- a/vlc-android/res/menu/media_library.xml
> +++ b/vlc-android/res/menu/media_library.xml
> @@ -25,4 +25,8 @@
> android:id="@+id/ml_menu_refresh"
> android:icon="@drawable/ic_menu_refresh"
> android:title="@string/refresh" />
> + <item
> + android:id="@+id/ml_menu_open_stream"
> + android:icon="@android:drawable/ic_btn_speak_now"
> + android:title="@string/open_stream" />
> </menu>
> diff --git a/vlc-android/res/values/strings.xml b/vlc-android/res/values/strings.xml
> index 541132b..b1810ac 100644
> --- a/vlc-android/res/values/strings.xml
> +++ b/vlc-android/res/values/strings.xml
> @@ -78,4 +78,5 @@
> <string name="track_video_info">Codec: %1$s\nResolution: %2$dx%3$d</string>
> <string name="track_text">Subtitles track</string>
> <string name="track_unknown">Unknown track</string>
> + <string name="open_stream">Open Stream</string>
> </resources>
> diff --git a/vlc-android/src/org/videolan/vlc/AudioService.java b/vlc-android/src/org/videolan/vlc/AudioService.java
> index 233c276..cd681d2 100644
> --- a/vlc-android/src/org/videolan/vlc/AudioService.java
> +++ b/vlc-android/src/org/videolan/vlc/AudioService.java
> @@ -292,7 +292,7 @@ public class AudioService extends Service {
> return;
> }
> }
> - mLibVLC.readMedia(mCurrentMedia.getPath());
> + mLibVLC.readMedia(mCurrentMedia.getMRL());
> 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.getMRL());
> mHandler.sendEmptyMessage(SHOW_PROGRESS);
> showNotification();
> updateWidget(this);
> @@ -418,7 +418,7 @@ public class AudioService extends Service {
> if (mCurrentMedia != null)
> return mCurrentMedia.getTitle();
> else
> - return null;
> + return "(null)";
Why?
> }
>
> public Bitmap getCover() {
> @@ -470,6 +470,10 @@ public class AudioService extends Service {
> for (int i = 0; i < mediaPathList.size(); i++) {
> String path = mediaPathList.get(i);
> Media media = db.getMedia(AudioService.this, path);
> + if(media == null) {
> + Log.v(TAG, "Creating remote Media object for " + path);
> + media = new Media(AudioService.this, path);
> + }
> mMediaList.add(media);
> }
>
> @@ -478,7 +482,7 @@ public class AudioService extends Service {
> }
>
> if (mCurrentMedia != null)
> - mLibVLC.readMedia(mCurrentMedia.getPath());
> + mLibVLC.readMedia(mCurrentMedia.getMRL());
> showNotification();
> }
>
> diff --git a/vlc-android/src/org/videolan/vlc/Media.java b/vlc-android/src/org/videolan/vlc/Media.java
> index 9f1662c..25c2cdc 100644
> --- a/vlc-android/src/org/videolan/vlc/Media.java
> +++ b/vlc-android/src/org/videolan/vlc/Media.java
> @@ -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;
> @@ -63,6 +65,7 @@ public class Media implements Comparable<Media> {
> private String mTrackID;
>
> private File mFile;
> + private String mMRL;
> private long mTime = 0;
> private long mLength = 0;
> private int mType;
> @@ -76,7 +79,10 @@ public class Media implements Comparable<Media> {
> */
> public Media(Context context, File file) {
> this.mFile = file;
> -
> + // LibVLC expects the file:///sdcard/... format, but by default
> + // Java gives file:/sdcard, which angers LibVLC
> + mMRL = file.toURI().toString().replace("file:/", "file:///");
> +
I see this same code is used below, this should go into one unique place
so we don't forget to use it.
FixURI(file.toURI()) ?
> LibVLC mLibVlc = null;
> try {
> mLibVlc = LibVLC.getInstance();
> @@ -112,10 +118,57 @@ public class Media implements Comparable<Media> {
> DatabaseManager db = DatabaseManager.getInstance(context);
> db.addMedia(this);
> }
> +
> + /**
> + * Create a new remote Media
> + * @param file: any valid MRL that LibVLC accepts
> + */
Thanks for highlighting this problem.
There should not be a notion of "remote Media", all medias are the same
for VLC, wether they are files or not.
That's why even for files we should use URLs (or MRLs).
And new_media() should use libvlc_media_new_location.
libvlc_media_new_path() just calls libvlc_media_new_location() with
unmodified argument if it is already an URI, else it adds file:// and
URL encodes the file path.
Since java can give us URIs already (although a bit buggy like you
noticed) then we should use them everywhere, it would be much simpler.
I will add this to my TODO list if you don't want to work on it, else I
think I and others can help you on IRC since we went through this
already in VLC some time ago (as wisely pointed out by courmisch).
> + public Media(Context context, String _mrl) {
> + this.mFile = null;
> + this.mMRL = _mrl;
> +
> + LibVLC mLibVlc = null;
> + try {
> + mLibVlc = LibVLC.getInstance();
> + mType = (mLibVlc.hasVideoTrack(mMRL)) ? TYPE_VIDEO : TYPE_AUDIO;
> + mLength = mLibVlc.getLengthFromFile(mMRL);
> +
> + String[] array = mLibVlc.readMediaMeta(mMRL);
> +
> + int i;
> + for (i = 0; i < array.length; i++) {
> + String s = array[i++];
> + String v = array[i];
> +
> + if (s.equals("title")) {
> + mTitle = v;
> + Log.d(TAG, "Title " + mTitle);
> + } else if (s.equals("artist")) {
> + mArtist = Util.getValue(context, v, R.string.unknown_artist);
> + Log.d(TAG, "Artist " + mArtist);
> + } else if (s.equals("genre")) {
> + mGenre = Util.getValue(context, v, R.string.unknown_genre);
> + Log.d(TAG, "Genre " + mGenre);
> + } else if (s.equals("album")) {
> + mAlbum = Util.getValue(context, v, R.string.unknown_album);
> + Log.d(TAG, "Album " + mAlbum);
> + }
> + }
> + } catch (LibVlcException e) {
> + e.printStackTrace();
> + }
> +
> + // 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,
> Bitmap picture, String title, String artist, String genre, String album) {
> mFile = file;
> + // LibVLC expects the file:///sdcard/... format, but by default
> + // Java gives file:/sdcard, which angers LibVLC
> + mMRL = file.toURI().toString().replace("file:/", "file:///");
> mTime = time;
> mLength = length;
> mType = type;
> @@ -134,13 +187,33 @@ public class Media implements Comparable<Media> {
> return mTitle.toUpperCase().compareTo(
> another.getTitle().toUpperCase());
> }
> +
> + /**
> + * Convert to string for debugging aid
> + */
> + public String toString() {
> + String buf = "";
> + buf += "Media information:\n";
> + buf += "Media Path: " + ((mFile == null) ? "none" : mFile.getPath());
> + buf += "Media MRL: " + mMRL.toString();
> + buf += "Media Title: " + mTitle;
> + return buf;
> + }
>
> public File getFile() {
> return mFile;
> }
>
> public String getPath() {
> - return mFile.getPath();
> + if(mFile == null) {
> + return mMRL;
> + } else {
> + return mFile.getPath();
> + }
> + }
> +
> + public String getMRL() {
> + return mMRL;
> }
>
> public void updateMeta() {
> @@ -190,7 +263,10 @@ public class Media implements Comparable<Media> {
>
> public String getTitle() {
> if (mTitle == null)
> - return mFile.getName().substring(0, mFile.getName().lastIndexOf('.'));
> + if (mFile != null)
> + return mFile.getName().substring(0, mFile.getName().lastIndexOf('.'));
> + else
> + return mMRL;
> else
> return mTitle;
> }
That's weird, libvlc has a fallback for when there is no title metadata
already, it should set Title to the filename or something.
Title metadata should never be NULL.
> diff --git a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> index 2660948..42049a5 100644
> --- a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> +++ b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> @@ -20,8 +20,12 @@
>
> package org.videolan.vlc.gui;
>
> +import java.util.ArrayList;
> +import java.util.List;
> +
> import org.videolan.vlc.AudioServiceController;
> import org.videolan.vlc.LibVLC;
> +import org.videolan.vlc.LibVlcException;
> import org.videolan.vlc.MediaLibrary;
> import org.videolan.vlc.R;
> import org.videolan.vlc.gui.audio.AudioActivityGroup;
> @@ -33,10 +37,12 @@ import org.videolan.vlc.widget.AudioMiniPlayer;
>
> import android.app.Activity;
> import android.app.ActivityGroup;
> +import android.app.AlertDialog;
> import android.app.Dialog;
> import android.app.TabActivity;
> import android.content.BroadcastReceiver;
> import android.content.Context;
> +import android.content.DialogInterface;
> import android.content.Intent;
> import android.content.IntentFilter;
> import android.content.SharedPreferences;
> @@ -232,6 +238,28 @@ public class MainActivity extends TabActivity {
> case R.id.ml_menu_refresh:
> MediaLibrary.getInstance(this).loadMediaItems(this);
> break;
> + case R.id.ml_menu_open_stream:
> + AlertDialog.Builder b = new AlertDialog.Builder(this);
> + final android.widget.EditText input = new android.widget.EditText(this);
> + b.setTitle("Resource MRL");
> + b.setMessage("e.g. rtsp:// or http://");
> + b.setView(input);
> + b.setPositiveButton("Open", new DialogInterface.OnClickListener() {
> + public void onClick(DialogInterface dialog, int button) {
> + AudioServiceController c = AudioServiceController.getInstance();
> + ArrayList<String> media = new ArrayList<String>();
> + media.add(input.getText().toString());
> + c.append(media);
> + }
> + }
> + );
> + b.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
> + @Override
> + public void onClick(DialogInterface arg0, int arg1) {
> + return;
> + }});
> + b.show();
> + break;
> }
> return super.onOptionsItemSelected(item);
> }
> diff --git a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserActivity.java b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserActivity.java
> index 0e9a76f..e486257 100644
> --- a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserActivity.java
> +++ b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserActivity.java
> @@ -20,6 +20,7 @@
>
> package org.videolan.vlc.gui.audio;
>
> +import java.util.ArrayList;
> import java.util.Collections;
> import java.util.Comparator;
> import java.util.List;
> @@ -192,8 +193,7 @@ public class AudioBrowserActivity extends Activity implements ISortable {
> else
> mAudioController.load(medias, start_position);
>
> - Intent intent = new Intent(AudioBrowserActivity.this, AudioPlayerActivity.class);
> - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
> + Intent intent = new Intent(AudioBrowserActivity.this, AudioPlayerActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
unintended?
> startActivity(intent);
> return super.onContextItemSelected(item);
> }
More information about the Android
mailing list