Better handling of state tracking in the UI. It now tracks what gst does, instead of just guessing from the buttons the user pressed.

This commit is contained in:
Xavi Artigas 2012-09-21 14:29:11 +02:00
parent 81bb469d72
commit a11dffbbc1
2 changed files with 39 additions and 8 deletions

View file

@ -40,6 +40,7 @@ static JavaVM *java_vm;
static jfieldID custom_data_field_id;
static jmethodID set_message_method_id;
static jmethodID set_current_position_method_id;
static jmethodID set_current_state_method_id;
static jmethodID on_gstreamer_initialized_method_id;
/*
@ -92,7 +93,7 @@ static void set_ui_message (const gchar *message, CustomData *data) {
static void set_current_ui_position (gint position, gint duration, CustomData *data) {
JNIEnv *env = get_jni_env ();
GST_DEBUG ("Setting current position/duration to: %d / %d (ms)", position, duration);
// GST_DEBUG ("Setting current position/duration to: %d / %d (ms)", position, duration);
(*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration);
if ((*env)->ExceptionCheck (env)) {
GST_ERROR ("Failed to call Java method");
@ -151,16 +152,22 @@ static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
}
static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
JNIEnv *env = get_jni_env ();
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
/* Only pay attention to messages coming from the pipeline, not its children */
if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) {
set_ui_message (gst_element_state_get_name (new_state), data);
data->state = new_state;
if (data->state >= GST_STATE_PAUSED && GST_CLOCK_TIME_IS_VALID (data->desired_position)) {
execute_seek (data->desired_position, data);
data->desired_position = GST_CLOCK_TIME_NONE;
}
GST_DEBUG ("State changed to %s, notifying application", gst_element_state_get_name(new_state));
(*env)->CallVoidMethod (env, data->app, set_current_state_method_id, new_state);
if ((*env)->ExceptionCheck (env)) {
GST_ERROR ("Failed to call Java method");
(*env)->ExceptionClear (env);
}
}
}
@ -303,8 +310,11 @@ jboolean gst_class_init (JNIEnv* env, jclass klass) {
GST_DEBUG ("The MethodID for the setCurrentPosition method is %p", set_current_position_method_id);
on_gstreamer_initialized_method_id = (*env)->GetMethodID (env, klass, "onGStreamerInitialized", "()V");
GST_DEBUG ("The MethodID for the onGStreamerInitialized method is %p", on_gstreamer_initialized_method_id);
set_current_state_method_id = (*env)->GetMethodID (env, klass, "setCurrentState", "(I)V");
GST_DEBUG ("The MethodID for the setCurrentState method is %p", set_current_state_method_id);
if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id || ! on_gstreamer_initialized_method_id) {
if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id ||
!on_gstreamer_initialized_method_id || !set_current_state_method_id) {
GST_ERROR ("The calling class does not implement all necessary interface methods");
return JNI_FALSE;
}

View file

@ -71,7 +71,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
play.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
nativePlay();
playing = true;
}
});
@ -79,7 +78,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
pause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
nativePause();
playing = false;
}
});
@ -107,6 +105,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
super.onDestroy();
}
/* Called from native code */
private void setMessage(final String message) {
final TextView tv = (TextView) this.findViewById(R.id.textview_message);
runOnUiThread (new Runnable() {
@ -116,17 +115,18 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
});
}
/* Called from native code */
private void onGStreamerInitialized () {
if (initialization_data != null) {
playing = initialization_data.getBoolean("playing");
boolean should_play = initialization_data.getBoolean("playing");
int milliseconds = initialization_data.getInt("position");
Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms.");
Log.i ("GStreamer", "Restoring state, playing:" + should_play + " position:" + milliseconds + " ms.");
/* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the
* milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind
* where we were before. This, combined with seeking to keyframe positions, would skip one keyframe
* backwards on each iteration. */
nativeSetPosition(milliseconds + 1);
if (playing) {
if (should_play) {
nativePlay();
} else {
nativePause();
@ -136,6 +136,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
}
}
/* Called from native code */
private void setCurrentPosition(final int position, final int duration) {
final TextView tv = (TextView) this.findViewById(R.id.textview_time);
final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar);
@ -153,6 +154,26 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
this.duration = duration;
}
/* Called from native code */
private void setCurrentState (int state) {
Log.d ("GStreamer", "State has changed to " + state);
switch (state) {
case 1:
setMessage ("NULL");
break;
case 2:
setMessage ("READY");
break;
case 3:
setMessage ("PAUSED");
break;
case 4:
setMessage ("PLAYING");
break;
}
playing = (state == 4);
}
static {
System.loadLibrary("gstreamer_android");
System.loadLibrary("tutorial-1");