Commit 6a4806ce authored by Edward Wang's avatar Edward Wang Committed by Rafaël Carré

Dynamically respond to video ES changes

This will allow us to support dynamically ES-changing streams, more streaming formats (TS) and more video formats (such as OGG video).
Signed-off-by: Rafaël Carré's avatarRafaël Carré <funman@videolan.org>
parent bf4e638f
......@@ -164,6 +164,11 @@ static void vlc_event_callback(const libvlc_event_t *ev, void *data)
JNIEnv *env;
JavaVM *myVm = data;
int ev_opt_data = 0;
if(ev->type == libvlc_MediaPlayerVout) {
/* For determining the vout/ES track change */
ev_opt_data = ev->u.media_player_vout.new_count;
}
bool isAttached = false;
if (eventManagerInstance == NULL)
......@@ -187,9 +192,9 @@ static void vlc_event_callback(const libvlc_event_t *ev, void *data)
}
/* Find the callback ID */
jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(I)V");
jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(II)V");
if (methodID) {
(*env)->CallVoidMethod(env, eventManagerInstance, methodID, ev->type);
(*env)->CallVoidMethod(env, eventManagerInstance, methodID, ev->type, ev_opt_data);
} else {
LOGE("EventManager: failed to get the callback method");
}
......@@ -365,7 +370,7 @@ void Java_org_videolan_vlc_LibVLC_setEventManager(JNIEnv *env, jobject thiz, job
return;
}
jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(I)V");
jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(II)V");
if (!methodID) {
LOGE("setEventManager: failed to get the callback method");
return;
......@@ -526,6 +531,7 @@ void Java_org_videolan_vlc_LibVLC_readMedia(JNIEnv *env, jobject thiz,
libvlc_MediaPlayerPaused,
libvlc_MediaPlayerEndReached,
libvlc_MediaPlayerStopped,
libvlc_MediaPlayerVout,
};
int i;
for (i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); ++i)
......
......@@ -30,6 +30,7 @@ import java.util.Stack;
import org.videolan.vlc.gui.MainActivity;
import org.videolan.vlc.gui.audio.AudioPlayerActivity;
import org.videolan.vlc.gui.video.VideoPlayerActivity;
import org.videolan.vlc.interfaces.IAudioService;
import org.videolan.vlc.interfaces.IAudioServiceCallback;
import org.videolan.vlc.widget.VLCAppWidgetProvider;
......@@ -277,6 +278,21 @@ public class AudioService extends Service {
executeUpdate();
next();
break;
case EventManager.MediaPlayerVout:
if(msg.getData().getInt("data") > 0) {
Log.i(TAG, "Obtained video track");
mMediaList.clear();
hideNotification();
// Got video, switch to the video player
Intent intent = new Intent(VLCApplication.getAppContext(), VideoPlayerActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.putExtra("itemLocation", mCurrentMedia.getLocation());
// Don't lose the currently playing stream
intent.putExtra("dontParse", true);
startActivity(intent);
}
break;
default:
Log.e(TAG, "Event not handled");
break;
......@@ -613,12 +629,45 @@ public class AudioService extends Service {
}
if (mCurrentMedia != null) {
mLibVLC.readMedia(mCurrentMedia.getLocation(), true);
mLibVLC.readMedia(mCurrentMedia.getLocation());
showNotification();
updateWidget(AudioService.this);
}
}
@Override
public void showWithoutParse(String URI) throws RemoteException {
Log.v(TAG, "Showing playing URI " + URI);
// Show an URI without interrupting/losing the current stream
if(!mLibVLC.isPlaying())
return;
mEventManager.addHandler(mEventHandler);
mMediaList.clear();
mPrevious.clear();
// Prevent re-parsing the media, which would mean losing the connection
mCurrentMedia = new Media(
getApplicationContext(),
URI,
0,
0,
Media.TYPE_AUDIO,
null,
URI,
VLCApplication.getAppContext().getString(R.string.unknown_artist),
VLCApplication.getAppContext().getString(R.string.unknown_genre),
VLCApplication.getAppContext().getString(R.string.unknown_album),
0,
0,
"");
mMediaList.add(mCurrentMedia);
// Notify everyone
mHandler.sendEmptyMessage(SHOW_PROGRESS);
showNotification();
executeUpdate();
}
@Override
public void append(List<String> mediaPathList) throws RemoteException {
if (mMediaList.size() == 0) {
......
......@@ -235,6 +235,13 @@ public class AudioServiceController implements IAudioPlayerControl {
updateAudioPlayer();
}
public void showWithoutParse(String u) {
remoteProcedureCall(mAudioServiceBinder, Void.class, (Void)null, "showWithoutParse",
new Class<?>[] { String.class },
new Object[] { u } );
updateAudioPlayer();
}
@Override
public String getAlbum() {
return remoteProcedureCall(mAudioServiceBinder, String.class, (String)null, "getAlbum", null, null);
......
......@@ -57,6 +57,7 @@ public class EventManager {
//public static final int MediaPlayerTitleChanged = 0x10f;
//public static final int MediaPlayerSnapshotTaken = 0x110;
//public static final int MediaPlayerLengthChanged = 0x111;
public static final int MediaPlayerVout = 0x112;
//public static final int MediaListItemAdded = 0x200;
//public static final int MediaListWillAddItem = 0x201;
......@@ -111,9 +112,10 @@ public class EventManager {
}
/** This method is called by a native thread **/
public void callback(int event) {
public void callback(int event, int optional_data) {
Bundle b = new Bundle();
b.putInt("event", event);
b.putInt("data", optional_data);
for (int i = 0; i < mEventHandler.size(); i++) {
Message msg = Message.obtain();
msg.setData(b);
......
......@@ -227,6 +227,10 @@ public class LibVLC {
mAout.release();
}
public void readMedia(String mrl) {
readMedia(mLibVlcInstance, mrl, false);
}
/**
* Read a media.
*/
......
......@@ -20,7 +20,6 @@
package org.videolan.vlc.gui;
import java.io.IOException;
import java.util.ArrayList;
import org.videolan.vlc.AudioService;
......@@ -34,7 +33,6 @@ import org.videolan.vlc.VLCCallbackTask;
import org.videolan.vlc.gui.audio.AudioBrowserFragment;
import org.videolan.vlc.gui.video.VideoListAdapter;
import org.videolan.vlc.gui.video.VideoListFragment;
import org.videolan.vlc.gui.video.VideoPlayerActivity;
import org.videolan.vlc.interfaces.ISortable;
import org.videolan.vlc.widget.AudioMiniPlayer;
......@@ -479,23 +477,15 @@ public class MainActivity extends SherlockFragmentActivity {
AudioServiceController c = AudioServiceController.getInstance();
String s = input.getText().toString();
try {
if(!LibVLC.getExistingInstance().hasVideoTrack(s)) {
Log.d(TAG, "Auto-detected audio for " + s);
ArrayList<String> media = new ArrayList<String>();
media.add(input.getText().toString());
c.append(media);
} else {
Log.d(TAG, "Auto-detected Video for " + s);
Intent intent = new Intent(getApplicationContext(),
VideoPlayerActivity.class);
intent.putExtra("itemLocation", s);
startActivity(intent);
}
} catch(IOException e) {
/* VLC is unable to open the MRL */
return;
}
/* Use the audio player by default. If a video track is
* detected, then it will automatically switch to the video
* player. This allows us to support more types of streams
* (for example, RTSP and TS streaming) where ES can be
* dynamically adapted rather than a simple scan.
*/
ArrayList<String> media = new ArrayList<String>();
media.add(s);
c.append(media);
}
@Override
......
......@@ -25,12 +25,14 @@ import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import org.videolan.vlc.AudioServiceController;
import org.videolan.vlc.EventManager;
import org.videolan.vlc.LibVLC;
import org.videolan.vlc.LibVlcException;
import org.videolan.vlc.R;
import org.videolan.vlc.Util;
import org.videolan.vlc.gui.PreferencesActivity;
import org.videolan.vlc.gui.audio.AudioPlayerActivity;
import org.videolan.vlc.interfaces.IPlayerControl;
import org.videolan.vlc.interfaces.OnPlayerControlListener;
import org.videolan.vlc.widget.PlayerControlClassic;
......@@ -115,6 +117,12 @@ public class VideoPlayerActivity extends Activity {
private ImageButton mLock;
private ImageButton mSize;
/**
* For uninterrupted switching between audio and video mode
*/
private boolean mSwitchingView;
private boolean mEndReached;
// size of the video
private int mVideoHeight;
private int mVideoWidth;
......@@ -179,6 +187,9 @@ public class VideoPlayerActivity extends Activity {
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
mAudioMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
mSwitchingView = false;
mEndReached = false;
registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
try {
......@@ -201,10 +212,15 @@ public class VideoPlayerActivity extends Activity {
protected void onStart() {
super.onStart();
dimStatusBar(true);
mSwitchingView = false;
}
@Override
protected void onPause() {
if(mSwitchingView) {
super.onPause();
return;
}
long time = 0;
if (mLibVLC.isPlaying()) {
time = mLibVLC.getTime() - 5000;
......@@ -226,7 +242,7 @@ public class VideoPlayerActivity extends Activity {
@Override
protected void onDestroy() {
unregisterReceiver(mBatteryReceiver);
if (mLibVLC != null) {
if (mLibVLC != null && !mSwitchingView) {
mLibVLC.stop();
}
......@@ -235,9 +251,23 @@ public class VideoPlayerActivity extends Activity {
mAudioManager = null;
if(mSwitchingView) {
Log.d(TAG, "mLocation = \"" + mLocation + "\"");
AudioServiceController.getInstance().showWithoutParse(mLocation);
Intent i = new Intent(this, AudioPlayerActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(i);
}
//AudioServiceController.getInstance().unbindAudioService(this);
super.onDestroy();
}
@Override
protected void onResume() {
AudioServiceController.getInstance().bindAudioService(this);
super.onResume();
}
private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver()
{
@Override
......@@ -374,8 +404,17 @@ public class VideoPlayerActivity extends Activity {
case EventManager.MediaPlayerEndReached:
Log.i(TAG, "MediaPlayerEndReached");
/* Exit player when reach the end */
mEndReached = true;
VideoPlayerActivity.this.finish();
break;
case EventManager.MediaPlayerVout:
if(msg.getData().getInt("data") == 0 && !mEndReached) {
/* Video track lost, open in audio mode */
Log.i(TAG, "Video track lost, switching to audio");
VideoPlayerActivity.this.mSwitchingView = true;
VideoPlayerActivity.this.finish();
}
break;
default:
Log.e(TAG, "Event not handled");
break;
......@@ -835,6 +874,7 @@ public class VideoPlayerActivity extends Activity {
String title = null;
String lastLocation = null;
long lastTime = 0;
boolean dontParse = false;
SharedPreferences preferences = getSharedPreferences(PreferencesActivity.NAME, MODE_PRIVATE);
if (getIntent().getAction() != null
......@@ -844,9 +884,10 @@ public class VideoPlayerActivity extends Activity {
} else if(getIntent().getExtras() != null) {
/* Started from VideoListActivity */
mLocation = getIntent().getExtras().getString("itemLocation");
dontParse = getIntent().getExtras().getBoolean("dontParse");
}
if (mLocation != null && mLocation.length() > 0) {
if (mLocation != null && mLocation.length() > 0 && !dontParse) {
mLibVLC.readMedia(mLocation, false);
mSurface.setKeepScreenOn(true);
......
......@@ -50,4 +50,5 @@ interface IAudioService {
void addAudioCallback(IAudioServiceCallback cb);
void removeAudioCallback(IAudioServiceCallback cb);
void detectHeadset(boolean enable);
void showWithoutParse(String URI);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment