gstplayer: Add play/stop sync API

- Add play/stop/pause sync API
      gst_player_play_sync()
      gst_player_stop_sync()
      gst_player_pause_sync()

https://bugzilla.gnome.org/show_bug.cgi?id=778390

Upstream Status:  [i.MX specific]

Signed-off-by: Lyon Wang <lyon.wang@nxp.com>

Conflicts:
	gst-libs/gst/player/gstplayer.c
diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
index 4d7cf0c..c975561 100644
--- a/gst-libs/gst/player/gstplayer.c
+++ b/gst-libs/gst/player/gstplayer.c
@@ -200,6 +200,10 @@
   gchar *audio_sid;
   gchar *subtitle_sid;
   gulong stream_notify_id;
+
+  /* When error occur, will set this flag to TRUE,
+   * so that it could quit for sync play/stop loop */
+  gboolean got_error;
 };
 
 struct _GstPlayerClass
@@ -298,6 +302,7 @@
   self->seek_position = GST_CLOCK_TIME_NONE;
   self->last_seek_time = GST_CLOCK_TIME_NONE;
   self->inhibit_sigs = FALSE;
+  self->got_error = FALSE;
 
   GST_TRACE_OBJECT (self, "Initialized");
 }
@@ -1056,6 +1061,8 @@
   GST_ERROR_OBJECT (self, "Error: %s (%s, %d)", err->message,
       g_quark_to_string (err->domain), err->code);
 
+  self->got_error = TRUE;
+
   if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
           signals[SIGNAL_ERROR], 0, NULL, NULL, NULL) != 0) {
     ErrorSignalData *data = g_new (ErrorSignalData, 1);
@@ -5069,3 +5076,108 @@
 
   return self->app_state;
 }
+
+/**
+ * gst_player_wait_state
+ * @player: #GstPlayer instance
+ * @target_state: target state
+ * @time_out:  time out value
+ *  negtive (< 0): infinitely waiting for state change.
+ *  positive (>0): wait until time out.
+ *  zero (0), do not wait for the state change.
+ *
+ * Wait for target state, quit loop when time out
+ */
+static void
+gst_player_wait_state (GstPlayer * self, GstPlayerState target_state,
+    gint time_out)
+{
+  gint wait_cnt = 0;
+
+  while (time_out < 0 || wait_cnt < time_out * 20) {
+    if (self->app_state == target_state) {
+      break;
+    } else if (self->got_error == TRUE) {
+      self->got_error = FALSE;
+      return;
+    } else if (self->is_eos == TRUE) {
+      return;
+    } else {
+      wait_cnt++;
+      usleep (50000);
+    }
+  }
+  if (time_out > 0 && wait_cnt >= time_out * 20) {
+    emit_error (self, g_error_new (GST_PLAYER_ERROR,
+            GST_PLAYER_ERROR_FAILED,
+            "try to play /stop /pause failed, time out"));
+  }
+
+  return;
+}
+
+/**
+ * gst_player_play_sync:
+ * @player: #GstPlayer instance
+ * @time_out:  time out value
+ *  negtive (< 0): infinitely waiting for state change.
+ *  positive (>0): wait until time out.
+ *  zero (0), do not wait for the state change.
+ *
+ * Request to play the loaded stream in sync mode.
+ */
+void
+gst_player_play_sync (GstPlayer * self, gint time_out)
+{
+  g_return_if_fail (GST_IS_PLAYER (self));
+
+  gst_player_play (self);
+
+  gst_player_wait_state (self, GST_PLAYER_STATE_PLAYING, time_out);
+
+  return;
+}
+
+/**
+ * gst_player_stop_sync:
+ * @player: #GstPlayer instance
+ * @time_out:  time out value
+ *  negtive (< 0): infinitely waiting for state change.
+ *  positive (>0): wait until time out.
+ *  zero (0), do not wait for the state change.
+ *
+ *  Stops playing the current stream in sync mode.
+ */
+void
+gst_player_stop_sync (GstPlayer * self, gint time_out)
+{
+  g_return_if_fail (GST_IS_PLAYER (self));
+
+  gst_player_stop (self);
+
+  gst_player_wait_state (self, GST_PLAYER_STATE_STOPPED, time_out);
+
+  return;
+}
+
+/**
+ * gst_player_pause_sync:
+ * @player: #GstPlayer instance
+ * @time_out:  time out value
+ *  negtive (< 0): infinitely waiting for state change.
+ *  positive (>0): wait until time out.
+ *  zero (0), do not wait for the state change.
+ *
+ *  Pause current stream in sync mode.
+ */
+void
+gst_player_pause_sync (GstPlayer * self, gint time_out)
+{
+  g_return_if_fail (GST_IS_PLAYER (self));
+
+  gst_player_pause (self);
+
+  gst_player_wait_state (self, GST_PLAYER_STATE_PAUSED, time_out);
+
+  return;
+}
diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h
index ffecc1d..f2f0ab1 100644
--- a/gst-libs/gst/player/gstplayer.h
+++ b/gst-libs/gst/player/gstplayer.h
@@ -304,6 +304,10 @@
 
 GstPlayerState  gst_player_get_state (GstPlayer * player);
 
+void         gst_player_play_sync (GstPlayer * player, gint time_out);
+void         gst_player_stop_sync (GstPlayer * player, gint time_out);
+void         gst_player_pause_sync (GstPlayer * player, gint time_out);
+
 G_END_DECLS
 
 #endif /* __GST_PLAYER_H__ */