[meego-commits] 24225: Changes to devel:tv:1.2/UMMS

zwu28 no_reply at build.meego.com
Thu Oct 13 08:14:17 UTC 2011


Hi,
I have made the following changes to UMMS in project devel:tv:1.2. Please review and accept ASAP.

Thank You,
zwu28

[This message was auto-generated]

---

Request #24225:

  submit:   home:zwu28:branches:devel:tv:1.2/UMMS(r15)(update) -> devel:tv:1.2/UMMS


Message:
    None

State:   new          2011-10-13T01:02:21 zwu28
Comment: None



changes files:
--------------
--- umms.changes
+++ umms.changes
@@ -0,0 +1,8 @@
+Thu Oct 13 2011 Zhiwen Wu <zhiwen.wu at intel.com>- 0.0.1
+- Fix Bug "Playback stopped when typed a invalid path to record the dvb-ts streaming."
+- Fix Bug "Unable to play mp4 files via meego-tv-browser"
+
+Thu Oct 13 2011 Junyan He <Junyan.he at intel.com>- 0.0.1
+- test UI improvement. 
+- Socket feedback solution improvement.
+

spec files:
-----------

other changes:
--------------

++++++ umms-0.0.1.tar.gz
--- spec/umms-media-player.xml
+++ spec/umms-media-player.xml
@@ -228,23 +228,19 @@
 			<arg name="protocol_name" type="s" direction="out"/>
 		</method>
 
-		<method name="GetProtocolName">
-			<arg name="protocol_name" type="s" direction="out"/>
-		</method>
-
 		<method name="Record">
 			<arg name="record" type="b"/>
 			<arg name="location" type="s"/>
 		</method>
 
-    <method name="GetPat">
-      <arg name="pat" type="aa{sv}" direction="out"/>
+		<method name="GetPat">
+			<arg name="pat" type="aa{sv}" direction="out"/>
 		</method>
 
-    <method name="GetPmt">
-      <arg name="program-number" type="u" direction="out"/>
-      <arg name="pcr-pid" type="u" direction="out"/>
-      <arg name="stream-info" type="aa{sv}" direction="out"/>
+		<method name="GetPmt">
+			<arg name="program-number" type="u" direction="out"/>
+			<arg name="pcr-pid" type="u" direction="out"/>
+			<arg name="stream-info" type="aa{sv}" direction="out"/>
 		</method>
 
 		<method name="GetCurrentUri">
--- src/dvb-player.c
+++ src/dvb-player.c
@@ -55,8 +55,8 @@
 #define INVALID_PLANE_ID -1
 
 #define SOCK_MAX_SERV_CONNECTS 5
-#define SOCK_SOCKET_DEFAULT_PORT 112131
-#define SOCK_SOCKET_DEFAULT_ADDR NULL
+#define SOCK_SOCKET_DEFAULT_PORT 0 // The port number will be get by socket create.
+#define SOCK_SOCKET_DEFAULT_ADDR "127.0.0.1"
 
 
 static const gchar *gst_state[] = {
@@ -1403,6 +1403,16 @@
     file_location = location;
   else
     file_location = DEFAULT_FILE_LOCATION;
+
+  //validate the location 
+  FILE *fd = fopen (file_location, "wb");
+  if (fd == NULL) {
+    UMMS_DEBUG ("Could not open file \"%s\" for writing.", file_location);
+    goto out;
+  } else {
+    fclose (fd);
+  }
+
   UMMS_DEBUG ("location: '%s'", file_location);
   g_object_set (filesink, "location", file_location, NULL);
 
@@ -1440,6 +1450,7 @@
     gst_object_unref (sinkpad);
 
   if (!ret) {
+    TEARDOWN_ELEMENT (filesink);
     UMMS_DEBUG ("failed!!!");
   }
 
@@ -1447,7 +1458,6 @@
 
 failed:
   gst_bin_remove (GST_BIN(priv->pipeline), filesink);
-  TEARDOWN_ELEMENT (filesink);
   goto out;
 }
 
@@ -2683,7 +2693,6 @@
 
   g_mutex_lock (priv->socks_lock);
   priv->sock_exit_flag = 1;
-  g_mutex_unlock (priv->socks_lock);
 
   if (priv->listen_fd != -1) { /* need to wakeup the listen thread. */
     struct hostent *host = gethostbyname("localhost");
@@ -2695,11 +2704,15 @@
       server_addr.sin_addr = *((struct in_addr*)host->h_addr);
 
       UMMS_DEBUG("try to wakeup the thread by connect");
+      g_mutex_unlock (priv->socks_lock);
       connect (fd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
       close(fd);
     } else {
+      g_mutex_unlock (priv->socks_lock);
       UMMS_DEBUG("socket create failed, can not wakeup the listen thread");
-    }
+    } 
+  } else {
+    g_mutex_unlock (priv->socks_lock);//Just Unlock it.
   }
 
   g_thread_join(priv->listen_thread);
@@ -2772,35 +2785,44 @@
     }
     priv->serv_fds[i] = -1;
   }
-  g_mutex_unlock (priv->socks_lock);
-
+  
   priv->listen_fd = socket(AF_INET, SOCK_STREAM, 0);
   if (priv->listen_fd < 0) {
-    UMMS_DEBUG("The listen socket create failed!");
+    UMMS_DEBUG("The listen socket create failed!");    
+    g_mutex_unlock (priv->socks_lock);
     return NULL;
   }
 
   memset(&serv_addr, 0, sizeof(serv_addr));
   serv_addr.sin_family = AF_INET;
-  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  serv_addr.sin_addr.s_addr = inet_addr(priv->ip);
   serv_addr.sin_port = htons(priv->port);
   if (bind(priv->listen_fd, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr)) == -1) {
     UMMS_DEBUG("try to binding to %s:%d Failed, error is %s",
                priv->ip, priv->port, strerror(errno));
     close(priv->listen_fd);
-    priv->listen_fd = -1;
+    priv->listen_fd = -1;    
+    g_mutex_unlock (priv->socks_lock);
     return NULL;
   }
 
   serv_len = sizeof(struct sockaddr);
-  if (getsockname(priv->listen_fd, (struct sockaddr *)&serv_addr, &serv_len) == 0) {
-    UMMS_DEBUG("we now binding to %s:%d", inet_ntoa(serv_addr.sin_addr), priv->port);
+  if (getsockname(priv->listen_fd, (struct sockaddr *)&serv_addr, &serv_len) != 0) {
+    UMMS_DEBUG("We can not get the port of listen_fd");
+    close(priv->listen_fd);
+    priv->listen_fd = -1;    
+    g_mutex_unlock (priv->socks_lock);
+    return NULL;
   }
+  
+  UMMS_DEBUG("we now binding to %s:%d", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
+  priv->port = ntohs(serv_addr.sin_port);
+  g_mutex_unlock (priv->socks_lock);
 
   if (listen(priv->listen_fd, 5) == -1) {
     UMMS_DEBUG("Listen Failed, error us %s", strerror(errno));
     close(priv->listen_fd);
-    priv->listen_fd = -1;
+    priv->listen_fd = -1;    
     return NULL;
   }
 
--- src/engine-gst.c
+++ src/engine-gst.c
@@ -1227,6 +1227,7 @@
 {
   GstElement *pipe;
   EngineGstPrivate *priv;
+  gboolean ret = TRUE;
 
   g_return_val_if_fail (self != NULL, FALSE);
   g_return_val_if_fail (MEEGO_IS_MEDIA_PLAYER_CONTROL(self), FALSE);
@@ -1236,10 +1237,13 @@
   g_return_val_if_fail (GST_IS_ELEMENT (pipe), FALSE);
 
   UMMS_DEBUG ("set playback rate to %f ", in_rate);
-  return gst_element_seek (pipe, in_rate,
+  ret = gst_element_seek (pipe, in_rate,
          GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+         
+  if (ret)
+    meego_media_player_control_emit_seeked (self);
 }
 
 static gboolean
@@ -2396,6 +2400,7 @@
 engine_gst_get_audio_samplerate(MeegoMediaPlayerControl *self, gint channel, gint * sample_rate)
 {
   GstElement *pipe = NULL;
+  EngineGstPrivate *priv = NULL;
   int tol_channel;
   GstCaps *caps = NULL;
   GstPad *pad = NULL;
@@ -2408,6 +2413,8 @@
   g_return_val_if_fail (MEEGO_IS_MEDIA_PLAYER_CONTROL(self), FALSE);
 
   /* We get this kind of infomation from the caps of inputselector. */
+  priv = GET_PRIVATE (self);
+  pipe = priv->pipeline;
 
   g_object_get (G_OBJECT (pipe), "n-audio", &tol_channel, NULL);
   UMMS_DEBUG ("the audio number of the stream is %d, want to get: %d",
@@ -2443,6 +2450,7 @@
     gint * frame_rate_num, gint * frame_rate_denom)
 {
   GstElement *pipe = NULL;
+  EngineGstPrivate *priv = NULL;
   int tol_channel;
   GstCaps *caps = NULL;
   GstPad *pad = NULL;
@@ -2456,6 +2464,8 @@
   g_return_val_if_fail (MEEGO_IS_MEDIA_PLAYER_CONTROL(self), FALSE);
 
   /* We get this kind of infomation from the caps of inputselector. */
+  priv = GET_PRIVATE (self);
+  pipe = priv->pipeline;
 
   g_object_get (G_OBJECT (pipe), "n-video", &tol_channel, NULL);
   UMMS_DEBUG ("the video number of the stream is %d, want to get: %d",
@@ -2490,6 +2500,7 @@
 engine_gst_get_video_resolution(MeegoMediaPlayerControl *self, gint channel, gint * width, gint * height)
 {
   GstElement *pipe = NULL;
+  EngineGstPrivate *priv = NULL;
   int tol_channel;
   GstCaps *caps = NULL;
   GstPad *pad = NULL;
@@ -2502,7 +2513,9 @@
   g_return_val_if_fail (MEEGO_IS_MEDIA_PLAYER_CONTROL(self), FALSE);
 
   /* We get this kind of infomation from the caps of inputselector. */
-
+  priv = GET_PRIVATE (self);
+  pipe = priv->pipeline;
+  
   g_object_get (G_OBJECT (pipe), "n-video", &tol_channel, NULL);
   UMMS_DEBUG ("the video number of the stream is %d, want to get: %d",
               tol_channel, channel);
@@ -2538,6 +2551,7 @@
     gint * ratio_num, gint * ratio_denom)
 {
   GstElement *pipe = NULL;
+  EngineGstPrivate *priv = NULL;
   int tol_channel;
   GstCaps *caps = NULL;
   GstPad *pad = NULL;
@@ -2551,6 +2565,8 @@
   g_return_val_if_fail (MEEGO_IS_MEDIA_PLAYER_CONTROL(self), FALSE);
 
   /* We get this kind of infomation from the caps of inputselector. */
+  priv = GET_PRIVATE (self);
+  pipe = priv->pipeline;
 
   g_object_get (G_OBJECT (pipe), "n-video", &tol_channel, NULL);
   UMMS_DEBUG ("the video number of the stream is %d, want to get: %d",
@@ -2585,6 +2601,7 @@
 engine_gst_get_protocol_name(MeegoMediaPlayerControl *self, gchar ** prot_name)
 {
   GstElement *pipe = NULL;
+  EngineGstPrivate *priv = NULL;
   gchar * uri = NULL;
 
   *prot_name = NULL;
@@ -2592,6 +2609,9 @@
   g_return_val_if_fail (self != NULL, FALSE);
   g_return_val_if_fail (MEEGO_IS_MEDIA_PLAYER_CONTROL(self), FALSE);
 
+  priv = GET_PRIVATE (self);
+  pipe = priv->pipeline;
+
   g_object_get (G_OBJECT (pipe), "uri", &uri, NULL);
 
   if (!uri) {
--- src/meego-media-player-control.c
+++ src/meego-media-player-control.c
@@ -266,14 +266,15 @@
 gboolean
 meego_media_player_control_get_position (MeegoMediaPlayerControl *self, gint64 *cur_time)
 {
+  gboolean ret = FALSE;
   meego_media_player_control_get_position_impl impl = (MEEGO_MEDIA_PLAYER_CONTROL_GET_CLASS (self)->get_position);
 
   if (impl != NULL) {
-    (impl) (self, cur_time);
+    ret = (impl) (self, cur_time);
   } else {
     g_warning ("Method not implemented\n");
   }
-  return TRUE;
+  return ret;
 }
 
 
@@ -1298,15 +1299,16 @@
 
 gboolean meego_media_player_control_record (MeegoMediaPlayerControl *self, gboolean to_record, gchar *location)
 {
+  gboolean ret = FALSE;
   meego_media_player_control_record_impl impl =
     (MEEGO_MEDIA_PLAYER_CONTROL_GET_CLASS (self)->record);
 
   if (impl != NULL) {
-    (impl) (self, to_record, location);
+    ret = (impl) (self, to_record, location);
   } else {
     g_warning ("Method not implemented\n");
   }
-  return TRUE;
+  return ret;
 }
 
 void meego_media_player_control_implement_record  (MeegoMediaPlayerControlClass *klass,
--- src/meego-media-player.c
+++ src/meego-media-player.c
@@ -453,8 +453,7 @@
     GError **err)
 {
   CHECK_ENGINE(GET_CONTROL_IFACE (player), FALSE, err);
-  meego_media_player_control_get_position (GET_CONTROL_IFACE (player), pos);
-  return TRUE;
+  return meego_media_player_control_get_position (GET_CONTROL_IFACE (player), pos);
 }
 
 gboolean
@@ -690,6 +689,7 @@
   gboolean ret = TRUE;
   MeegoMediaPlayerPrivate *priv = GET_PRIVATE (player);
 
+  UMMS_DEBUG ("Want to set the suburi to %s", sub_uri);
   if (player->player_control) {
     ret = meego_media_player_control_set_subtitle_uri (GET_CONTROL_IFACE (player), sub_uri);
   } else {
@@ -1344,9 +1344,13 @@
 gboolean 
 meego_media_player_record (MeegoMediaPlayer *player, gboolean to_record, gchar *location, GError **err)
 {
+  gboolean ret;
   CHECK_ENGINE(GET_CONTROL_IFACE (player), FALSE, err);
-  meego_media_player_control_record (GET_CONTROL_IFACE (player), to_record, location);
-  return TRUE;
+  ret = meego_media_player_control_record (GET_CONTROL_IFACE (player), to_record, location);
+  if (!ret) {
+    g_set_error (err, UMMS_ENGINE_ERROR, UMMS_ENGINE_ERROR_FAILED, "Record failed");
+  }
+  return ret;
 }
 
 gboolean 
--- test/ui/gtk-backend-umms.c
+++ test/ui/gtk-backend-umms.c
@@ -58,11 +58,16 @@
     dbus_g_proxy_add_signal (player, "Seeked", G_TYPE_INVALID);
     dbus_g_proxy_add_signal (player, "Stopped", G_TYPE_INVALID);
 
+    dbus_g_proxy_add_signal (player, "VideoTagChanged", G_TYPE_INT, G_TYPE_INVALID);
+    dbus_g_proxy_add_signal (player, "AudioTagChanged", G_TYPE_INT, G_TYPE_INVALID);
+    dbus_g_proxy_add_signal (player, "TextTagChanged", G_TYPE_INT, G_TYPE_INVALID);
+
     dbus_g_object_register_marshaller (umms_marshal_VOID__UINT_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
     dbus_g_proxy_add_signal (player, "Error", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
-    dbus_g_proxy_add_signal (player, "PlayerStateChanged", G_TYPE_INT, G_TYPE_INVALID);
-}
 
+    dbus_g_object_register_marshaller (umms_marshal_VOID__INT_INT, G_TYPE_NONE, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID);
+    dbus_g_proxy_add_signal (player, "PlayerStateChanged", G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID);
+}
 
 static void __initialized_cb(DBusGProxy *player, gpointer user_data)
 {
@@ -72,35 +77,43 @@
 static void __player_state_changed_cb(DBusGProxy *player, gint state, gpointer user_data)
 {
     UMMS_DEBUG("State changed to '%s'", state_name[state]);
+    ui_callbacks_for_reason(UI_CALLBACK_STATE_CHANGE, (void *)state, NULL);
 }
 
 static void __eof_cb(DBusGProxy *player, gpointer user_data)
 {
     UMMS_DEBUG( "EOF....");
+    ui_callbacks_for_reason(UI_CALLBACK_EOF, NULL, NULL);
 }
 
 static void __begin_buffering_cb(DBusGProxy *player, gpointer user_data)
 {
+    UMMS_DEBUG( "BUFFERING ....");
+    ui_callbacks_for_reason(UI_CALLBACK_BUFFERING, NULL, NULL);
 }
 
 static void __buffered_cb(DBusGProxy *player, gpointer user_data)
 {
     UMMS_DEBUG( "Buffering completed");
+    ui_callbacks_for_reason(UI_CALLBACK_BUFFERED, NULL, NULL);
 }
 
 static void __seeked_cb(DBusGProxy *player, gpointer user_data)
 {
     UMMS_DEBUG( "Seeking completed");
+    ui_callbacks_for_reason(UI_CALLBACK_SEEKED, NULL, NULL);
 }
 
 static void __stopped_cb(DBusGProxy *player, gpointer user_data)
 {
     UMMS_DEBUG( "Player stopped");
+    ui_callbacks_for_reason(UI_CALLBACK_STOPPED, NULL, NULL);
 }
 
 static void __error_cb(DBusGProxy *player, guint err_id, gchar *msg, gpointer user_data)
 {
     UMMS_DEBUG( "Error Domain:'%s', msg='%s'", error_type[err_id], msg);
+    ui_callbacks_for_reason(UI_CALLBACK_ERROR, (void *)err_id, (void *)msg);
 }
 
 static void __request_window_cb(DBusGProxy *player, gpointer user_data)
@@ -108,6 +121,24 @@
     UMMS_DEBUG( "Player engine request a X window");
 }
 
+static void __video_tag_changed_cb(DBusGProxy *player, guint stream_id, gpointer user_data)
+{
+    UMMS_DEBUG( "Video tag changed");
+    ui_callbacks_for_reason(UI_CALLBACK_VIDEO_TAG_CHANGED, (void *)stream_id, NULL);
+}
+
+static void __audio_tag_changed_cb(DBusGProxy *player, guint stream_id, gpointer user_data)
+{
+    UMMS_DEBUG( "Audio tag changed");
+    ui_callbacks_for_reason(UI_CALLBACK_AUDIO_TAG_CHANGED, (void *)stream_id, NULL);
+}
+
+static void __text_tag_changed_cb(DBusGProxy *player, guint stream_id, gpointer user_data)
+{
+    UMMS_DEBUG( "Text tag changed");
+    ui_callbacks_for_reason(UI_CALLBACK_TEXT_TAG_CHANGED, (void *)stream_id, NULL);
+}
+
 static void
 connect_sigs(DBusGProxy *player)
 {
@@ -156,6 +187,21 @@
             "PlayerStateChanged",
             G_CALLBACK(__player_state_changed_cb),
             NULL, NULL);
+
+    dbus_g_proxy_connect_signal (player,
+            "VideoTagChanged",
+            G_CALLBACK(__video_tag_changed_cb),
+            NULL, NULL);
+
+    dbus_g_proxy_connect_signal (player,
+            "AudioTagChanged",
+            G_CALLBACK(__audio_tag_changed_cb),
+            NULL, NULL);
+
+    dbus_g_proxy_connect_signal (player,
+            "TextTagChanged",
+            G_CALLBACK(__text_tag_changed_cb),
+            NULL, NULL);
 }
 
 
@@ -249,7 +295,12 @@
     GError *error = NULL;
     gchar * file_name;
 
-    file_name = g_strdup_printf("file://%s", filename);
+    if (filename && filename[0] == '/') {
+        file_name = g_strdup_printf("file://%s", filename);
+    } else {
+        file_name = g_strdup(filename);
+    }
+
     printf("file_name is %s\n", file_name);
     if (!dbus_g_proxy_call (player, "SetUri", &error,
             G_TYPE_STRING, file_name, G_TYPE_INVALID,
@@ -261,6 +312,30 @@
     return 0;
 }
 
+
+gint avdec_set_subtitle(gchar *filename)
+{
+    GError *error = NULL;
+    gchar * file_name;
+
+    if (filename && filename[0] == '/') {
+        file_name = g_strdup_printf("file://%s", filename);
+    } else {
+        file_name = g_strdup(filename);
+    }
+
+    printf("subtitle file_name is %s\n", file_name);
+    if (!dbus_g_proxy_call (player, "SetSubtitleUri", &error,
+            G_TYPE_STRING, file_name, G_TYPE_INVALID,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to SetSubtitleUri", error);
+        return -1;
+    }
+    g_free(file_name);
+    return 0;
+}
+
+
 gint avdec_start(void)
 {
     GError *error = NULL;
@@ -316,9 +391,516 @@
     if (!dbus_g_proxy_call (player, "SetPosition", &error,
             G_TYPE_INT64, nanosecond,
             G_TYPE_INVALID, G_TYPE_INVALID)) {
-        UMMS_GERROR ("Failed to SetUri", error);
+        UMMS_GERROR ("Failed to SetPosition", error);
+        return -1;
+    }
+    return 0;
+}
+
+gint avdec_set_speed(int speed)
+{
+    GError *error = NULL;
+
+    if (!dbus_g_proxy_call (player, "SetPlaybackRate", &error,
+            G_TYPE_DOUBLE, (gdouble)speed,
+            G_TYPE_INVALID, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to set_speed", error);
         return -1;
     }
     return 0;
 }
 
+
+gint avdec_get_speed(void)
+{
+    GError *error = NULL;
+    gdouble speed;
+
+    if (!dbus_g_proxy_call (player, "GetPlaybackRate", &error,
+            G_TYPE_INVALID, G_TYPE_DOUBLE, &speed,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to get_speed", error);
+        return 1;
+    }
+    return (gint)speed;
+}
+
+
+gint avdec_get_duration(gint64 * len)
+{
+    GError *error = NULL;
+    gint64 dur;
+
+    if (!dbus_g_proxy_call (player, "GetMediaSizeTime", &error,
+            G_TYPE_INVALID, G_TYPE_INT64, &dur,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to get_duration", error);
+        return -1;
+    }
+
+    //printf("Current duration = %lli\n", dur);
+    *len = dur;
+    return 0;
+}
+
+gint avdec_get_position(gint64 * pos)
+{
+    GError *error = NULL;
+    gint64 cur_pos;
+
+    if (!dbus_g_proxy_call (player, "GetPosition", &error,
+            G_TYPE_INVALID, G_TYPE_INT64, &cur_pos,
+            G_TYPE_INVALID)) {
+        printf ("Failed to get_position\n");
+        //UMMS_GERROR ("Failed to get_position", error);
+        return -1;
+    }
+
+    printf("Current pos = %lli\n", cur_pos);
+    *pos = cur_pos;
+    return 0;
+}
+
+gint avdec_get_video_num(gint * video_num)
+{
+    GError *error = NULL;
+    gint video;
+
+    if (!dbus_g_proxy_call (player, "GetVideoNum", &error,
+            G_TYPE_INVALID, G_TYPE_INT, &video,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoNum", error);
+        return -1;
+    }
+
+    *video_num = video;
+    return 0;
+}
+
+
+gint avdec_get_cur_video(gint * cur_video)
+{
+    GError *error = NULL;
+    gint video;
+
+    if (!dbus_g_proxy_call (player, "GetCurrentVideo", &error,
+            G_TYPE_INVALID, G_TYPE_INT, &video,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetCurrentVideo", error);
+        return -1;
+    }
+
+    *cur_video = video;
+    return 0;
+}
+
+gint avdec_set_cur_video(gint cur_video)
+{
+    GError *error = NULL;
+
+    if (!dbus_g_proxy_call (player, "SetCurrentVideo", &error,
+            G_TYPE_INT, cur_video,
+            G_TYPE_INVALID, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to set_cur_video", error);
+        return -1;
+    }
+    return 0;
+
+}
+
+gint avdec_get_video_codec(gint video, gchar ** codec_name)
+{
+    GError *error = NULL;
+    gchar * name;
+
+    if (!dbus_g_proxy_call (player, "GetVideoCodec", &error,
+            G_TYPE_INT, video, G_TYPE_INVALID,
+            G_TYPE_STRING, &name, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoCodec", error);
+        return -1;
+    }
+
+    *codec_name = g_strdup(name);
+    g_free(name);
+    return 0;
+}
+
+
+gint avdec_get_audio_num(gint * audio_num)
+{
+    GError *error = NULL;
+    gint audio;
+
+    if (!dbus_g_proxy_call (player, "GetAudioNum", &error,
+            G_TYPE_INVALID, G_TYPE_INT, &audio,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoNum", error);
+        return -1;
+    }
+
+    *audio_num = audio;
+    return 0;
+}
+
+
+gint avdec_get_cur_audio(gint * cur_audio)
+{
+    GError *error = NULL;
+    gint audio;
+
+    if (!dbus_g_proxy_call (player, "GetCurrentAudio", &error,
+            G_TYPE_INVALID, G_TYPE_INT, &audio,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetCurrentAudio", error);
+        return -1;
+    }
+
+    *cur_audio = audio;
+    return 0;
+}
+
+gint avdec_set_cur_audio(gint cur_audio)
+{
+    GError *error = NULL;
+
+    if (!dbus_g_proxy_call (player, "SetCurrentAudio", &error,
+            G_TYPE_INT, cur_audio,
+            G_TYPE_INVALID, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to set_cur_audio", error);
+        return -1;
+    }
+    return 0;
+
+}
+
+
+gint avdec_get_audio_codec(gint audio, gchar ** codec_name)
+{
+    GError *error = NULL;
+    gchar * name;
+
+    if (!dbus_g_proxy_call (player, "GetAudioCodec", &error,
+            G_TYPE_INT, audio, G_TYPE_INVALID,
+            G_TYPE_STRING, &name, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetAudioCodec", error);
+        return -1;
+    }
+
+    *codec_name = g_strdup(name);
+    g_free(name);
+    return 0;
+}
+
+
+gint avdec_get_encapsulation(gchar ** container_name)
+{
+    GError *error = NULL;
+    gchar * name;
+
+    if (!dbus_g_proxy_call (player, "GetEncapsulation", &error,
+            G_TYPE_INVALID,
+            G_TYPE_STRING, &name, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetEncapsulation", error);
+        return -1;
+    }
+
+    *container_name = g_strdup(name);
+    g_free(name);
+    return 0;
+}
+
+
+gint avdec_get_video_bitrate(gint video_num, gint * bit_rate)
+{
+    GError *error = NULL;
+    gint rate;
+
+    if (!dbus_g_proxy_call (player, "GetVideoBitrate", &error,
+            G_TYPE_INT, video_num, G_TYPE_INVALID,
+            G_TYPE_INT, &rate, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoBitrate", error);
+        return -1;
+    }
+
+    *bit_rate = rate;
+    return 0;
+}
+
+gint avdec_get_video_framerate(gint video_num, gint * rate_num, gint * rate_denom)
+{
+    GError *error = NULL;
+    gint num, denom;
+
+    if (!dbus_g_proxy_call (player, "GetVideoFramerate", &error,
+            G_TYPE_INT, video_num, G_TYPE_INVALID,
+            G_TYPE_INT, &num,
+            G_TYPE_INT, &denom,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoFramerate", error);
+        return -1;
+    }
+
+    //printf("================= num %d, demon: %d\n", num, denom);
+    *rate_num = num;
+    *rate_denom = denom;
+    return 0;
+}
+
+
+gint avdec_get_video_resolution(gint video_num, gint * width, gint * height)
+{
+    GError *error = NULL;
+    gint width_, height_;
+
+    if (!dbus_g_proxy_call (player, "GetVideoResolution", &error,
+            G_TYPE_INT, video_num, G_TYPE_INVALID,
+            G_TYPE_INT, &width_,
+            G_TYPE_INT, &height_,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoResolution", error);
+        return -1;
+    }
+
+    //printf("resolution is %d X %d\n", width_, height_);
+    *width = width_;
+    *height = height_;
+    return 0;
+}
+
+
+gint avdec_get_video_aspectratio(gint video_num, gint * ratio_num, gint * ratio_denom)
+{
+    GError *error = NULL;
+    gint num, denom;
+
+    if (!dbus_g_proxy_call (player, "GetVideoAspectRatio", &error,
+            G_TYPE_INT, video_num, G_TYPE_INVALID,
+            G_TYPE_INT, &num,
+            G_TYPE_INT, &denom,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVideoAspectRatio", error);
+        return -1;
+    }
+
+    //printf("================= num %d, demon: %d\n", num, denom);
+    *ratio_num = num;
+    *ratio_denom = denom;
+    return 0;
+}
+
+
+gint avdec_get_audio_bitrate(gint audio_num, gint * bit_rate)
+{
+    GError *error = NULL;
+    gint rate;
+
+    if (!dbus_g_proxy_call (player, "GetAudioBitrate", &error,
+            G_TYPE_INT, audio_num, G_TYPE_INVALID,
+            G_TYPE_INT, &rate, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetAudioBitrate", error);
+        return -1;
+    }
+
+    *bit_rate = rate;
+    return 0;
+}
+
+gint avdec_get_audio_samplerate(gint audio_num, gint * sample_rate)
+{
+    GError *error = NULL;
+    gint rate;
+
+    if (!dbus_g_proxy_call (player, "GetAudioSamplerate", &error,
+            G_TYPE_INT, audio_num, G_TYPE_INVALID,
+            G_TYPE_INT, &rate, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetAudioBitrate", error);
+        return -1;
+    }
+
+    *sample_rate = rate;
+    return 0;
+}
+
+gint avdec_get_current_uri(gchar ** uri)
+{
+    GError *error = NULL;
+    gchar * uri_str;
+
+    if (!dbus_g_proxy_call (player, "GetCurrentUri", &error,
+            G_TYPE_INVALID,
+            G_TYPE_STRING, &uri_str, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetCurrentUri", error);
+        return -1;
+    }
+
+    *uri = g_strdup(uri_str);
+    g_free(uri_str);
+    return 0;
+}
+
+gint avdec_get_protocol_name(gchar **name)
+{
+    GError *error = NULL;
+    gchar * prot_str;
+
+    if (!dbus_g_proxy_call (player, "GetProtocolName", &error,
+            G_TYPE_INVALID,
+            G_TYPE_STRING, &prot_str, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetProtocolName", error);
+        return -1;
+    }
+
+    *name = g_strdup(prot_str);
+    g_free(prot_str);
+    return 0;
+}
+
+gint avdec_set_volume(gint volume)
+{
+    GError *error = NULL;
+
+    if (!dbus_g_proxy_call (player, "SetVolume", &error,
+            G_TYPE_INT, volume,
+            G_TYPE_INVALID, G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to SetVolume", error);
+        return -1;
+    }
+
+    return 0;
+}
+
+gint avdec_get_volume(gint *volume)
+{
+    GError *error = NULL;
+    gint vol;
+
+    if (!dbus_g_proxy_call (player, "GetVolume", &error,
+            G_TYPE_INVALID,
+            G_TYPE_INT, &vol,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetVolume", error);
+        return -1;
+    }
+
+    *volume = vol;
+    return 0;
+}
+
+gint avdec_get_rawdata_address(gchar ** ip_addr, gint * port)
+{
+    GError *error = NULL;
+    gchar * ip_addr_;
+    gint port_;
+
+    if (!dbus_g_proxy_call (player, "GetAssociatedDataChannel", &error,
+            G_TYPE_INVALID,
+            G_TYPE_STRING, &ip_addr_,
+            G_TYPE_INT, &port_,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetAssociatedDataChannel", error);
+        return -1;
+    }
+
+    *ip_addr = g_strdup(ip_addr_);
+    *port = port_;
+    return 0;
+}
+
+gint avdec_get_pat(GArray ** ret_array)
+{
+    GError *error = NULL;
+    GPtrArray *pat_array;
+    GHashTable *hash_table;
+    int length;
+    int i;
+    struct UMMS_Pat_Item pat_itm;
+    GValue *val = NULL;
+
+    if (!dbus_g_proxy_call (player, "GetPat", &error,
+            G_TYPE_INVALID,
+            dbus_g_type_get_collection("GPtrArray",
+                    dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)),
+            &pat_array,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetPat", error);
+        return -1;
+    }
+
+    length = pat_array->len;
+    //printf("the hash ptr length is %d\n", length);
+
+    if (length <= 0)
+        return -1;
+
+    *ret_array = g_array_new(FALSE, FALSE, sizeof(struct UMMS_Pat_Item));
+
+    for (i = 0; i < length; i++) {
+        hash_table = g_ptr_array_index(pat_array, i);
+        val = g_hash_table_lookup(hash_table, "program-number");
+        pat_itm.program_num = g_value_get_uint(val);
+
+        val = g_hash_table_lookup(hash_table, "pid");
+        pat_itm.pid = g_value_get_uint(val);
+
+        g_array_append_val(*ret_array, pat_itm);
+    }
+
+    g_ptr_array_foreach(pat_array, (GFunc)g_hash_table_remove_all, NULL);
+    g_ptr_array_free(pat_array, FALSE);
+
+    return 0;
+}
+
+gint avdec_get_pmt(guint *ret_program_num, guint *ret_pcr_pid, GArray ** ret_array)
+{
+    GError *error = NULL;
+    GPtrArray *pmt_array;
+    GHashTable *hash_table;
+    int length;
+    int i;
+    struct UMMS_Pmt_Item pmt_itm;
+    guint program_num;
+    guint pcr_pid;
+    guint stream_type;
+    GValue *val = NULL;
+
+    if (!dbus_g_proxy_call (player, "GetPmt", &error,
+            G_TYPE_INVALID,
+            G_TYPE_UINT, &program_num,
+            G_TYPE_UINT, &pcr_pid,
+            dbus_g_type_get_collection("GPtrArray",
+                    dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)),
+            &pmt_array,
+            G_TYPE_INVALID)) {
+        UMMS_GERROR ("Failed to GetPmt", error);
+        return -1;
+    }
+
+    length = pmt_array->len;
+    //printf("the hash ptr length is %d\n", length);
+
+    if (length <= 0)
+        return -1;
+
+    *ret_array = g_array_new(FALSE, FALSE, sizeof(struct UMMS_Pmt_Item));
+
+    for (i = 0; i < length; i++) {
+        hash_table = g_ptr_array_index(pmt_array, i);
+        val = g_hash_table_lookup(hash_table, "pid");
+        pmt_itm.pid = g_value_get_uint(val);
+
+        val = g_hash_table_lookup(hash_table, "stream-type");
+        pmt_itm.stream_type = g_value_get_uint(val);
+
+        g_array_append_val(*ret_array, pmt_itm);
+    }
+
+    g_ptr_array_foreach(pmt_array, (GFunc)g_hash_table_remove_all, NULL);
+    g_ptr_array_free(pmt_array, FALSE);
+
+    *ret_program_num = program_num;
+    *ret_pcr_pid = pcr_pid;
+
+    return 0;
+}
+
--- test/ui/gtk-backend.h
+++ test/ui/gtk-backend.h
@@ -25,6 +25,17 @@
 #ifndef AV_DECODER_H_
 #define AV_DECODER_H_
 
+
+typedef struct UMMS_Pat_Item {
+    guint program_num;
+    guint pid;
+}UMMS_Pat_Item;
+
+typedef struct UMMS_Pmt_Item {
+    guint pid;
+    guint stream_type;
+}UMMS_Pmt_Item;
+
 gint avdec_init(void);
 gint avdec_set_source(gchar *filename);
 gint avdec_start(void);
--- test/ui/umms-gtk-player.c
+++ test/ui/umms-gtk-player.c
@@ -37,26 +37,95 @@
 
 gint ply_init(void)
 {
+    ply_main_data.state_lock = g_mutex_new ();
     ply_main_data.state = PLY_MAIN_STATE_IDLE;
+    ply_main_data.play_speed = 1;
     avdec_init();
     return 0;
 }
 
-PlyMainData *ply_get_maindata(void)
+static void ply_update_duration(void * dummy)
 {
-    return &ply_main_data;
+    gint64 pos, len, volume;
+
+    if (ply_get_state() == PLY_MAIN_STATE_RUN) {
+        avdec_get_duration(&len);
+        avdec_get_position(&pos);
+        ui_update_progressbar(pos, len);
+    }
 }
 
 
 PlyMainState ply_get_state(void)
 {
-    return ply_main_data.state;
+    g_mutex_lock (ply_main_data.state_lock);
+    PlyMainState state = ply_main_data.state;
+    g_mutex_unlock (ply_main_data.state_lock);
+    return state;
+}
+
+
+void ply_set_state(PlyMainState state)
+{
+    static guint dur_timeout_id = 0;
+
+    g_mutex_lock (ply_main_data.state_lock);
+    ply_main_data.state = state;
+    g_print("%s\n", dbg_state_name[ply_main_data.state]);
+
+    if (state == PLY_MAIN_STATE_RUN) {
+        if (dur_timeout_id == 0) {
+            dur_timeout_id = g_timeout_add(1000, (GSourceFunc)ply_update_duration, NULL);
+        }
+    } else {
+        if (dur_timeout_id != 0) {
+            g_source_remove (dur_timeout_id);
+            dur_timeout_id = 0;
+        }
+    }
+
+    g_mutex_unlock (ply_main_data.state_lock);
+}
+
+
+gint ply_get_speed(void)
+{
+    g_mutex_lock (ply_main_data.state_lock);
+    gint speed = ply_main_data.play_speed;
+    g_mutex_unlock (ply_main_data.state_lock);
+    return speed;
 }
 
+
+void ply_set_speed(gint speed)
+{
+    g_mutex_lock (ply_main_data.state_lock);
+    ply_main_data.play_speed = speed;
+    g_mutex_unlock (ply_main_data.state_lock);
+}
+
+
+gint64 ply_get_duration(void)
+{
+    g_mutex_lock (ply_main_data.state_lock);
+    gint64 len = ply_main_data.duration_nanosecond;
+    g_mutex_unlock (ply_main_data.state_lock);
+    return len;
+}
+
+
+void ply_set_duration(gint64 len)
+{
+    g_mutex_lock (ply_main_data.state_lock);
+    ply_main_data.duration_nanosecond = len;
+    g_mutex_unlock (ply_main_data.state_lock);
+}
+
+
 gint ply_reload_file(gchar *filename)
 {
-    if (ply_main_data.state != PLY_MAIN_STATE_IDLE &&
-         ply_main_data.state != PLY_MAIN_STATE_READY) {
+    if (ply_get_state() != PLY_MAIN_STATE_IDLE &&
+         ply_get_state() != PLY_MAIN_STATE_READY) {
         ply_stop_stream();
     }
 
@@ -68,47 +137,38 @@
     return 0;
 }
 
+gint ply_set_subtitle(gchar *filename)
+{
+    if (ply_get_state() == PLY_MAIN_STATE_IDLE ||
+         ply_get_state() == PLY_MAIN_STATE_READY) {
+        avdec_set_subtitle (filename);
+    }
+
+    return 0;
+}
+
 gint ply_play_stream(void)
 {
     avdec_start();
-    ply_main_data.state = PLY_MAIN_STATE_RUN;
 
-    g_print("%s\n", dbg_state_name[ply_main_data.state]);
     return 0;
 }
 
 gint ply_stop_stream(void)
 {
-    /* If main state is idle or ready, remain its current state */
-    if (ply_main_data.state != PLY_MAIN_STATE_IDLE &&
-         ply_main_data.state != PLY_MAIN_STATE_READY) {
-        avdec_stop();
-        ply_main_data.state = PLY_MAIN_STATE_READY;
-    }
-
-    g_print("%s\n", dbg_state_name[ply_main_data.state]);
+    avdec_stop();
     return 0;
 }
 
 gint ply_pause_stream(void)
 {
-    if (ply_main_data.state == PLY_MAIN_STATE_RUN) {
-        ply_main_data.state = PLY_MAIN_STATE_PAUSE;
-        avdec_pause();
-    }
-
-    g_print("%s\n", dbg_state_name[ply_main_data.state]);
+    avdec_pause();
     return 0;
 }
 
 gint ply_resume_stream(void)
 {
-    if (ply_main_data.state == PLY_MAIN_STATE_PAUSE) {
-        ply_main_data.state = PLY_MAIN_STATE_RUN;
-        avdec_resume();
-    }
-
-    g_print("%s\n", dbg_state_name[ply_main_data.state]);
+    avdec_resume();
     return 0;
 }
 
@@ -118,3 +178,157 @@
     return 0;
 }
 
+
+gint ply_forward_rewind(gint speed)
+{
+    avdec_set_speed(speed);
+    return 0;
+}
+
+
+gint ply_get_play_speed(void)
+{
+    return avdec_get_speed();
+}
+
+gint ply_get_video_num(void)
+{
+    gint video_num = 0;
+    avdec_get_video_num(&video_num);
+    return video_num;
+}
+
+gint ply_get_cur_video(void)
+{
+    gint cur_video = 0;
+    avdec_get_cur_video(&cur_video);
+    return cur_video;
+}
+
+gint ply_set_cur_video(gint cur_video)
+{
+    return avdec_set_cur_video(cur_video);
+}
+
+gchar* ply_get_video_codec(gint video_num)
+{
+    gchar * codec = 0;
+    avdec_get_video_codec(video_num, &codec);
+    return codec;
+}
+
+gint ply_get_audio_num(void)
+{
+    gint audio_num = 0;
+    avdec_get_audio_num(&audio_num);
+    return audio_num;
+}
+
+gint ply_get_cur_audio(void)
+{
+    gint cur_audio = 0;
+    avdec_get_cur_audio(&cur_audio);
+    return cur_audio;
+}
+
+gint ply_set_cur_audio(gint cur_audio)
+{
+    return avdec_set_cur_audio(cur_audio);
+}
+
+gchar* ply_get_audio_codec(gint audio_num)
+{
+    gchar * codec = 0;
+    avdec_get_audio_codec(audio_num, &codec);
+    return codec;
+}
+
+gchar* ply_get_container_name(void)
+{
+    gchar * name = 0;
+    avdec_get_encapsulation(&name);
+    return name;
+}
+
+gint ply_get_video_bitrate(gint video_num)
+{
+    int bitrate = 0;
+    avdec_get_video_bitrate(video_num, &bitrate);
+    return bitrate;
+}
+
+gdouble ply_get_video_framerate(gint video_num)
+{
+    gint rate_num, rate_denom;
+    avdec_get_video_framerate(video_num, &rate_num, &rate_denom);
+    return ((gdouble)rate_num) / ((gdouble)rate_denom);
+}
+
+gint ply_get_video_resolution(gint video_num, gint *width, gint *height)
+{
+    return avdec_get_video_resolution(video_num, width, height);
+}
+
+gint ply_get_video_aspectratio(gint video_num, gint *width, gint *height)
+{
+    return avdec_get_video_aspectratio(video_num, width, height);
+}
+
+gint ply_get_audio_bitrate(gint audio_num)
+{
+    int bitrate = 0;
+    avdec_get_audio_bitrate(audio_num, &bitrate);
+    return bitrate;
+}
+
+gint ply_get_audio_samplerate(gint audio_num)
+{
+    int sample_rate = 0;
+    avdec_get_audio_samplerate(audio_num, &sample_rate);
+    return sample_rate;
+}
+
+gchar* ply_get_current_uri(void)
+{
+    gchar * uri = NULL;
+    avdec_get_current_uri(&uri);
+    return uri;
+}
+
+gchar* ply_get_protocol_name(void)
+{
+    gchar * name = NULL;
+    avdec_get_protocol_name(&name);
+    return name;
+}
+
+gint ply_set_volume(gint volume)
+{
+    return avdec_set_volume(volume);
+}
+
+gint ply_get_volume(void)
+{
+    gint volume;
+    avdec_get_volume(&volume);
+    return volume;
+}
+
+gint ply_get_rawdata_address(gchar ** ip_addr, gint * port)
+{
+    avdec_get_rawdata_address(ip_addr, port);
+    return 0;
+}
+
+GArray *ply_get_pat(void)
+{
+    GArray * pat;
+    avdec_get_pat(&pat);
+    return pat;
+}
+
+gint ply_get_pmt(guint *program_num, guint *pcr_pid, GArray **array)
+{
+    return avdec_get_pmt(program_num, pcr_pid, array);
+}
+
--- test/ui/umms-gtk-player.h
+++ test/ui/umms-gtk-player.h
@@ -24,7 +24,6 @@
 
 #ifndef PLAYER_CORE_H_
 #define PLAYER_CORE_H_
-
 typedef enum _PlyMainState {
     PLY_MAIN_STATE_IDLE,
     PLY_MAIN_STATE_READY,
@@ -33,9 +32,11 @@
 }PlyMainState;
 
 typedef struct _PlyMainData {
+    GMutex *state_lock; 
     PlyMainState state;
     GString filename;
     gint64 duration_nanosecond;
+    gint play_speed;
 }PlyMainData;
 
 /***
@@ -45,8 +46,6 @@
  */
 gint ply_init(void);
 
-PlyMainData *ply_get_maindata(void);
-
 /***
  * @brief Get player main state
  *
@@ -61,6 +60,8 @@
  */
 gint ply_reload_file(gchar *file_name);
 
+gint ply_set_subtitle(gchar *filename);
+
 /***
  * @brief Play the stream from the very beginning, this function just needs to send the message to AV decoder thread, and returns without block.
  *
@@ -97,4 +98,53 @@
  */
 gint ply_seek_stream_from_beginging(gint64 nanosecond);
 
+
+gint ply_forward_rewind(gint speed);
+
+gint ply_get_play_speed(void);
+
+gint ply_get_video_num(void);
+
+gint ply_get_cur_video(void);
+
+gint ply_set_cur_video(gint cur_video);
+
+gchar* ply_get_video_codec(gint video_num);
+
+gint ply_get_audio_num(void);
+
+gint ply_get_cur_audio(void);
+
+gint ply_set_cur_audio(gint cur_audio);
+
+gchar* ply_get_audio_codec(gint audio_num);
+
+gchar* ply_get_container_name(void);
+
+gint ply_get_video_bitrate(gint video_num);
+
+gdouble ply_get_video_framerate(gint video_num);
+
+gint ply_get_video_resolution(gint video_num, gint *width, gint *height);
+
+gint ply_get_video_aspectratio(gint video_num, gint *width, gint *height);
+
+gint ply_get_audio_bitrate(gint audio_num);
+
+gint ply_get_audio_samplerate(gint audio_num);
+
+gchar* ply_get_current_uri(void);
+
+gchar* ply_get_protocol_name(void);
+
+gint ply_set_volume(gint volume);
+
+gint ply_get_volume(void);
+
+gint ply_get_rawdata_address(gchar ** ip_addr, gint * port);
+
+GArray *ply_get_pat(void);
+
+gint ply_get_pmt(guint *program_num, guint *pcr_pid, GArray **array);
+
 #endif /* PLAYER_CORE_H_ */
--- test/ui/umms-gtk-ui.c
+++ test/ui/umms-gtk-ui.c
@@ -20,7 +20,10 @@
  * License along with UMMS; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
+#include <unistd.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
@@ -32,6 +35,7 @@
 #include <gst/gst.h>
 #include "umms-gtk-player.h"
 #include "umms-gtk-ui.h"
+#include "gtk-backend.h"
 
 #define MY_GST_TIME_ARGS(t) \
             GST_CLOCK_TIME_IS_VALID (t) ? \
@@ -49,90 +53,564 @@
 static GtkWidget *progress_time;
 static GtkWidget *image_play;
 static GtkWidget *image_pause;
+static GtkWidget *volume_bar;
 
-static int av_sub_update_flag;
 static GtkWidget *video_combo;
 static GtkWidget *audio_combo;
 static GtkWidget *text_combo;
 
-int get_raw_data(void)
+GtkWidget *speed_lab;
+
+#define UPDATE_AUDIO_TAG 1
+#define UPDATE_VIDEO_TAG 1<<1
+#define UPDATE_TEXT_TAG 1<<2
+#define UPDATE_ALL UPDATE_AUDIO_TAG|UPDATE_VIDEO_TAG|UPDATE_TEXT_TAG
+
+static void ui_update_audio_video_text(gint what)
+{
+    GList * c_list = NULL;
+    gint i = 0;
+    gchar *codec_name = NULL;
+    gchar *show_name = NULL;
+
+    if (what & UPDATE_VIDEO_TAG) {
+        static int last_time_video_num = 0;
+        gint video_num = ply_get_video_num();
+        gint cur_video = ply_get_cur_video();
+
+        for (i = 0; i < last_time_video_num; i++)
+            gtk_combo_box_remove_text(GTK_COMBO_BOX(video_combo), 0);
+
+        last_time_video_num = video_num;
+
+        for (i = 0; i < video_num; i++) {
+            codec_name = ply_get_video_codec(i);
+            if (!codec_name || !strcmp(codec_name, "")) {
+                show_name = g_strdup_printf("Video %d: Format not known", i);
+            } else {
+                show_name = g_strdup_printf("Video %d: %s", i, codec_name);
+            }
+            g_free(codec_name);
+
+            if (i == cur_video) {
+                gtk_combo_box_prepend_text(GTK_COMBO_BOX(video_combo), show_name);
+            } else {
+                gtk_combo_box_append_text(GTK_COMBO_BOX(video_combo), show_name);
+            }
+
+            g_free(show_name);
+        }
+        gtk_combo_box_set_active (GTK_COMBO_BOX(video_combo), cur_video);
+    }
+
+
+    if (what & UPDATE_AUDIO_TAG) {
+        static int last_time_audio_num = 0;
+        gint audio_num = ply_get_audio_num();
+        gint cur_audio = ply_get_cur_audio();
+
+        for (i = 0; i < last_time_audio_num; i++)
+            gtk_combo_box_remove_text(GTK_COMBO_BOX(audio_combo), 0);
+
+        last_time_audio_num = audio_num;
+
+        for (i = 0; i < audio_num; i++) {
+            codec_name = ply_get_audio_codec(i);
+            if (codec_name == NULL) {// || !strcmp(codec_name, "")) {
+                show_name = g_strdup_printf("Audio %d: Format not known", i);
+            } else {
+                show_name = g_strdup_printf("Audio %d: %s", i, codec_name);
+            }
+            g_free(codec_name);
+
+            if (i == cur_audio) {
+                gtk_combo_box_prepend_text(GTK_COMBO_BOX(audio_combo), show_name);
+            } else {
+                gtk_combo_box_append_text(GTK_COMBO_BOX(audio_combo), show_name);
+            }
+
+            g_free(show_name);
+        }
+        gtk_combo_box_set_active (GTK_COMBO_BOX(audio_combo), cur_audio);
+    }
+}
+
+
+/* The callback for update status. */
+void ui_callbacks_for_reason(UI_CALLBACK_REASONS reason, void * data1, void * data2)
+{
+    printf("-------callback come for reason :%d\n", reason);
+    switch (reason) {
+        case UI_CALLBACK_STATE_CHANGE: {
+            if ((int)data1 == 2) {// Playing
+                gint play_speed;
+                char *str;
+
+                play_speed = ply_get_play_speed();
+                str = g_strdup_printf("  Play Speed: X %d   ", play_speed);
+                gtk_container_remove(GTK_CONTAINER(button_play), image_play);
+                gtk_container_add(GTK_CONTAINER(button_play), image_pause);
+                gtk_label_set_text(GTK_LABEL(speed_lab), str);
+                ply_set_state(PLY_MAIN_STATE_RUN);
+                ui_update_audio_video_text(UPDATE_ALL);
+                g_free(str);
+            } else {
+                gtk_container_remove(GTK_CONTAINER(button_play), image_pause);
+                gtk_container_add(GTK_CONTAINER(button_play), image_play);
+                gtk_label_set_text(GTK_LABEL(speed_lab), "  Play Speed: X 0   ");
+                if ((int)data1 == 1) {
+                    ply_set_state(PLY_MAIN_STATE_PAUSE);
+                } else if ((int)data1 == 3) {
+                    ply_set_state(PLY_MAIN_STATE_READY);
+                } else {
+                    ply_set_state(PLY_MAIN_STATE_IDLE);
+                }
+            }
+        }
+        break;
+
+        case UI_CALLBACK_EOF:
+            break;
+
+        case UI_CALLBACK_BUFFERING:
+            break;
+
+        case UI_CALLBACK_BUFFERED:
+            break;
+
+        case UI_CALLBACK_SEEKED: {
+            char *str;
+            gint play_speed;
+
+            play_speed = ply_get_play_speed();
+
+            str = g_strdup_printf("  Play Speed: X %d   ", play_speed);
+            gtk_label_set_text(GTK_LABEL(speed_lab), str);
+            g_free(str);
+            ply_set_speed(play_speed);
+        }
+        break;
+
+        case UI_CALLBACK_STOPPED:
+            gtk_label_set_text(GTK_LABEL(speed_lab), "  Play Speed: X 0   ");
+            gtk_container_remove(GTK_CONTAINER(button_play), image_pause);
+            gtk_container_add(GTK_CONTAINER(button_play), image_play);
+            ply_set_state(PLY_MAIN_STATE_READY);
+            break;
+
+        case UI_CALLBACK_ERROR:
+            break;
+
+        case UI_CALLBACK_VIDEO_TAG_CHANGED:
+            ui_update_audio_video_text(UPDATE_VIDEO_TAG);
+            break;
+
+        case UI_CALLBACK_AUDIO_TAG_CHANGED:
+            ui_update_audio_video_text(UPDATE_AUDIO_TAG);
+            break;
+
+        case UI_CALLBACK_TEXT_TAG_CHANGED:
+            break;
+
+        default:
+            printf("Error, should not come!!!!\n");
+            return;
+    }
+
+    gtk_widget_show_all(window);
+    return;
+}
+
+static int ui_create_socket(void)
 {
     int sockfd;
-    char buffer[1024];
     struct sockaddr_in server_addr;
-    int portnumber, nbytes;
-    struct hostent *host;
-    int i;
-
-    host = gethostbyname("localhost");
+    gchar * ip_address;
+    gint port;
+    int flags;
+
+    //host = gethostbyname("localhost");
+    ply_get_rawdata_address(&ip_address, &port);
+    printf("We get the socket address, IP: %s, port: %d\n", ip_address, port);
 
     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
         fprintf(stderr, "Socket Error:%s\a\n", (char *)strerror(errno));
-        return;
+        return -1;
     }
 
+
     memset(&server_addr, 0, sizeof(server_addr));
     server_addr.sin_family = AF_INET;
-    server_addr.sin_port = htons(112131);
-    server_addr.sin_addr = *((struct in_addr*)host->h_addr);
+    server_addr.sin_port = htons(port);
+    //server_addr.sin_addr = *((struct in_addr*)host->h_addr);
+    server_addr.sin_addr.s_addr = inet_addr(ip_address);
+    g_free(ip_address);
+
 
     if (connect (sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr)) == -1) {
         printf("Connect Error: %s\a\n", strerror(errno));
         close(sockfd);
-        return;
+        return -1;
     }
 
-    for (i = 0; i < 3; i++) {
-        nbytes = read(sockfd, buffer, 1024);
-        printf( "received:%d bytes\n", nbytes);
-        if (nbytes >= 0) {
-            buffer[nbytes] = '\0';
-            printf( "I have received:%x %x %x %x %x %x %x %x\n",
-                    buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
-                    buffer[5], buffer[6], buffer[7]);
+    flags = fcntl(sockfd, F_GETFL, 0);
+    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+
+    return sockfd;
+}
+
+static int ui_socket_fd = -1;
+
+static char * ui_get_raw_data(gint max_len, gint * ret_len)
+{
+    char buffer[1024];
+    fd_set fds;
+    int nbytes;
+    int i;
+    int maxfdp;
+    struct timeval tv;
+    gchar* ret_str;
+
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
+
+    while (1) {
+        FD_ZERO(&fds);
+        FD_SET(ui_socket_fd, &fds);
+        maxfdp = ui_socket_fd + 1;
+
+        switch (select(maxfdp, &fds, NULL, NULL, &tv)) {
+            case -1:
+                *ret_len = 0;
+                return NULL;
+                break;
+
+            case 0:
+                break;
+
+            default: {
+                if (FD_ISSET(ui_socket_fd, &fds)) {
+                    nbytes = read(ui_socket_fd, buffer, 1024);
+
+                    /*
+                    printf( "received:%d bytes\n", nbytes);
+                    if (nbytes >= 0) {
+                        buffer[nbytes] = '\0';
+                        printf( "I have received:%x %x %x %x %x %x %x %x\n",
+                        buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
+                        buffer[5], buffer[6], buffer[7]);
+                    }*/
+
+                    if (max_len <= 0)
+                        return; //do nothing
+
+                    max_len = (nbytes <= max_len) ? nbytes : max_len;
+                    ret_str = g_malloc(sizeof(gchar) * max_len);
+                    memcpy(ret_str, buffer, sizeof(gchar)*max_len);
+                    *ret_len = max_len;
+                    return ret_str;
+                }
+            }
         }
     }
-
-    close(sockfd);
+    *ret_len = 0;
+    return NULL;
 }
 
 
+
 static void ui_pause_bt_cb(GtkWidget *widget, gpointer data)
 {
+    //printf("the status is %d\n", ply_get_state());
     if (ply_get_state() == PLY_MAIN_STATE_READY) {
         ply_play_stream();
-        gtk_container_remove(GTK_CONTAINER(button_play), image_play);
-        gtk_container_add(GTK_CONTAINER(button_play), image_pause);
     } else if (ply_get_state() == PLY_MAIN_STATE_RUN) {
         ply_pause_stream();
-        gtk_container_remove(GTK_CONTAINER(button_play), image_pause);
-        gtk_container_add(GTK_CONTAINER(button_play), image_play);
     } else if (ply_get_state() == PLY_MAIN_STATE_PAUSE) {
         ply_resume_stream();
-        gtk_container_remove(GTK_CONTAINER(button_play), image_play);
-        gtk_container_add(GTK_CONTAINER(button_play), image_pause);
     }
     gtk_widget_show_all(window);
 }
 
 static void ui_stop_bt_cb(GtkWidget *widget, gpointer data)
 {
+    /* can stop anyway. */
+    ply_stop_stream();
+}
+
+static void ui_forward_bt_cb(GtkWidget *widget, gpointer data)
+{
+    gint speed = ply_get_speed();
+    if (speed <= 0) {
+        speed = 1;
+    } else {
+        speed = speed * 2;
+    }
+
+    if (ply_get_state() == PLY_MAIN_STATE_RUN) {
+        ply_forward_rewind(speed);
+    }
+}
+
+static void ui_rewind_bt_cb(GtkWidget *widget, gpointer data)
+{
+    gint speed = ply_get_speed();
+    if (speed >= 0) {
+        speed = -1;
+    } else {
+        speed = speed * 2;
+    }
+
     if (ply_get_state() == PLY_MAIN_STATE_RUN) {
-        ply_stop_stream();
-        gtk_container_remove(GTK_CONTAINER(button_play), image_pause);
-        gtk_container_add(GTK_CONTAINER(button_play), image_play);
-    } else if (ply_get_state() == PLY_MAIN_STATE_PAUSE) {
-        ply_stop_stream();
+        ply_forward_rewind(speed);
     }
 }
 
-static void ui_forward_bt_cb(GtkWidget *widget, gpointer data)
+static void ui_uri_open_bt_cb(GtkWidget *widget, gpointer data)
+{
+    GtkWidget *uri_dlg;
+    GtkWidget *uri_entry;
+    GtkWidget *sub_entry;
+    gint response_id;
+    gchar *entry_text = NULL;
+    gchar *sub_entry_text = NULL;
+    GtkWidget *frame;
+
+    uri_dlg = gtk_dialog_new_with_buttons("Enter the URI",
+              GTK_WINDOW(gtk_widget_get_toplevel (window)),
+              GTK_DIALOG_MODAL,
+              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+              GTK_STOCK_OK, GTK_RESPONSE_OK,
+              NULL);
+
+    gtk_window_set_default_size (GTK_WINDOW (uri_dlg), 500, 200);
+
+    frame = gtk_frame_new ("Type the URI:");
+
+    uri_entry = gtk_entry_new ();
+    gtk_entry_set_max_length (GTK_ENTRY (uri_entry), 500);
+
+    gtk_container_add (GTK_CONTAINER (frame), uri_entry);
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (uri_dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+
+    frame = gtk_frame_new ("Type the Subtitle URI:");
+
+    sub_entry = gtk_entry_new ();
+    gtk_entry_set_max_length (GTK_ENTRY (sub_entry), 500);
+
+    gtk_container_add (GTK_CONTAINER (frame), sub_entry);
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (uri_dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+
+    gtk_widget_show_all (uri_dlg);
+
+    response_id = gtk_dialog_run(GTK_DIALOG(uri_dlg));
+
+    if (response_id == GTK_RESPONSE_OK) {
+        entry_text = g_strdup(gtk_entry_get_text (GTK_ENTRY (uri_entry)));
+        sub_entry_text = g_strdup(gtk_entry_get_text (GTK_ENTRY (sub_entry)));
+        //printf("Entry contents: %s\n", entry_text);
+    }
+
+    gtk_widget_destroy(uri_dlg);
+
+    if (entry_text && entry_text[0]) {
+        ply_reload_file(entry_text);
+        if (sub_entry_text && sub_entry_text[0]) {
+            ply_set_subtitle(sub_entry_text);
+        }
+
+        ui_pause_bt_cb(NULL, NULL);
+        g_free(entry_text);
+    }
+}
+
+static void ui_sub_open_bt_cb(GtkWidget *widget, gpointer data)
 {
+    GtkWidget *subopen_dlg;
+    gint result;
+    gchar *filename;
+
+    subopen_dlg = gtk_file_chooser_dialog_new("Select Subtitle file",
+                  GTK_WINDOW(window),
+                  GTK_FILE_CHOOSER_ACTION_OPEN,
+                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                  GTK_STOCK_OK, GTK_RESPONSE_OK,
+                  NULL);
+    result = gtk_dialog_run(GTK_DIALOG(subopen_dlg));
+    if (GTK_RESPONSE_OK == result) {
+        filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(subopen_dlg));
+        gtk_widget_destroy(subopen_dlg);
+        g_print("subtitle filename is %s\n", filename);
+        ply_set_subtitle(filename);
+        g_free(filename);
+    } else {
+        gtk_widget_destroy(subopen_dlg);
+    }
+
 }
 
+static void ui_update_dvb_rawdata_thread(GtkWidget * uri_entry)
+{
+    gchar * raw_data = NULL;
+    gchar * show_data = NULL;
+    gint ret_len = 0;
+    gchar num_buf[16];
 
-static void ui_rewind_bt_cb(GtkWidget *widget, gpointer data)
+    if (ui_socket_fd == -1) {
+        ui_socket_fd = ui_create_socket();
+    }
+
+    if (ui_socket_fd != -1) {
+        int i;
+        struct timeval tv;
+        long tv_sec;
+
+        gettimeofday (&tv, NULL);
+        tv_sec = tv.tv_sec;
+
+        while (1) {
+            gchar * old = NULL;
+            raw_data = ui_get_raw_data(8, &ret_len);
+            if (raw_data == NULL)
+                break;
+
+            /* Do not append to quick. */
+            gettimeofday (&tv, NULL);
+            if (tv_sec == tv.tv_sec )
+                continue;
+
+            gtk_editable_delete_text(GTK_EDITABLE(uri_entry), 0, -1);
+
+            tv_sec = tv.tv_sec;
+            show_data = NULL;
+
+            for (i = 0; i < ret_len; i++) {
+                old = show_data;
+                sprintf(num_buf, "%2X", (char)raw_data[i]);
+
+                if (show_data) {
+                    show_data = g_strdup_printf("%s %s", old, num_buf);
+                } else {
+                    show_data = g_strdup(num_buf);
+                }
+                //printf("--- the num_buf = %s\n", num_buf);
+
+                if (old)
+                    g_free(old);
+            }
+
+            gtk_entry_set_text(GTK_ENTRY(uri_entry), show_data);
+            g_free(raw_data);
+        }
+    }
+}
+
+static void ui_dvb_bt_cb(GtkWidget *widget, gpointer data)
 {
+    GtkWidget *dlg;
+    gint result;
+    GtkWidget *frame;
+    GtkWidget *lab;
+    GtkWidget *uri_entry;
+    GThread *raw_data_update_thread;
+    GArray *pat;
+    GArray *pmt;
+    gchar * show_str = NULL;
+    guint program_num;
+    guint pcr_pid;
+    int i;
+
+    if (ply_get_state() != PLY_MAIN_STATE_RUN &&
+         ply_get_state() != PLY_MAIN_STATE_PAUSE) {
+        return;
+    }
+
+    dlg = gtk_dialog_new_with_buttons("DVB Infomation",
+            GTK_WINDOW(gtk_widget_get_toplevel (window)),
+            GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_OK,
+            NULL);
+    gtk_window_set_default_size (GTK_WINDOW ((dlg)), 600, 500);
+
+    frame = gtk_frame_new ("Raw Data Dump:");
+    uri_entry = gtk_entry_new ();
+    gtk_entry_set_max_length (GTK_ENTRY (uri_entry), 100);
+    gtk_container_add (GTK_CONTAINER (frame), uri_entry);
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+
+    /* Get the PAT and PMT. */
+    pat = ply_get_pat();
+    //printf("PAT array length is %d\n",  pat->len);
+
+    frame = gtk_frame_new ("Program  <----------->   PID");
+    show_str = NULL;
+    for (i = 0; i < pat->len; i++) {
+        struct UMMS_Pat_Item item = g_array_index(pat, UMMS_Pat_Item, i);
+
+        if (show_str) {
+            gchar * old = show_str;
+            show_str = g_strdup_printf("%s\nProgram Number: %u ----  PID: %u",
+                       show_str, item.program_num, item.pid);
+            g_free(old);
+        } else {
+            show_str = g_strdup_printf("Program Number: %u ----  PID: %u",
+                       item.program_num, item.pid);
+        }
+    }
+
+    lab = gtk_label_new(NULL);
+    gtk_label_set_text(GTK_LABEL(lab), show_str);
+    gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_FILL);
+    gtk_label_set_line_wrap (GTK_LABEL(lab), TRUE);
+    gtk_container_add (GTK_CONTAINER (frame), lab);
+
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+    g_array_free(pat, TRUE);
+    g_free(show_str);
+
+
+    if (ply_get_pmt(&program_num, &pcr_pid, &pmt) == 0) {
+        frame = gtk_frame_new ("Current Program Infomation:");
+        show_str = g_strdup_printf("Program Number: %u     PCR PID: %u",
+                   program_num, pcr_pid);
+        for (i = 0; i < pmt->len; i++) {
+            gchar * old = NULL;
+            struct UMMS_Pmt_Item item = g_array_index(pmt, UMMS_Pmt_Item, i);
+
+            old = show_str;
+            show_str = g_strdup_printf("%s\nPID: %u ----  Stream Type: %u",
+                       show_str, item.pid, item.stream_type);
+            g_free(old);
+        }
+
+        lab = gtk_label_new(NULL);
+        gtk_label_set_text(GTK_LABEL(lab), show_str);
+        gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_FILL);
+        gtk_label_set_line_wrap (GTK_LABEL(lab), TRUE);
+        gtk_container_add (GTK_CONTAINER (frame), lab);
+
+        gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox),
+                            frame, FALSE, FALSE, 0);
+        g_array_free(pmt, TRUE);
+        g_free(show_str);
+    }
+
+    gtk_widget_show_all (dlg);
+
+    raw_data_update_thread =
+        g_thread_create ((GThreadFunc) ui_update_dvb_rawdata_thread, uri_entry, TRUE, NULL);
+
+    gtk_dialog_run(GTK_DIALOG(dlg));
+
+    close(ui_socket_fd);
+    g_thread_join(raw_data_update_thread);
+    ui_socket_fd = -1;
+
+    gtk_widget_destroy(dlg);
 
 }
 
@@ -142,6 +620,21 @@
     GtkWidget *lab;
     GtkWidget *frame;
 
+    gchar * container_name = NULL;
+    gchar * codec_name = NULL;
+    gchar * show_name = NULL;
+    gchar * lab_str = NULL;
+    gchar * uri_str = NULL;
+    gchar * prot_str = NULL;
+    gint video_num = 0;
+    gint audio_num = 0;
+    int i = 0;
+
+    if (ply_get_state() != PLY_MAIN_STATE_RUN &&
+         ply_get_state() != PLY_MAIN_STATE_PAUSE) {
+        return;
+    }
+
     info_dlg = gtk_dialog_new_with_buttons("Media Info",
                GTK_WINDOW(gtk_widget_get_toplevel (window)),
                GTK_DIALOG_MODAL,
@@ -150,25 +643,134 @@
 
     gtk_window_set_default_size (GTK_WINDOW (info_dlg), 400, 400);
 
-    g_signal_connect (info_dlg, "destroy",
-                      G_CALLBACK (gtk_widget_destroyed),
-                      &info_dlg);
-
-    g_signal_connect (info_dlg, "response",
-                      G_CALLBACK (gtk_widget_destroy),
-                      NULL);
+    /* The uri and protocol. */
+    frame = gtk_frame_new ("Source");
+    lab = gtk_label_new(NULL);
+    uri_str = ply_get_current_uri();
+    prot_str = ply_get_protocol_name();
+    show_name = g_strdup_printf("URI: %s\nProtocol: %s", uri_str, prot_str);
+    gtk_label_set_text(GTK_LABEL(lab), show_name);
+    gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_FILL);
+    gtk_label_set_line_wrap (GTK_LABEL(lab), TRUE);
+    gtk_container_add (GTK_CONTAINER (frame), lab);
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (info_dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+    g_free(uri_str);
+    g_free(prot_str);
+    g_free(show_name);
+    show_name = NULL;
 
     /* Add the media info here. */
     frame = gtk_frame_new ("Container Type");
     lab = gtk_label_new(NULL);
-    gtk_label_set_text(GTK_LABEL(lab), "ASF");
+    container_name = ply_get_container_name();
+    gtk_label_set_text(GTK_LABEL(lab), container_name);
     gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_FILL);
     gtk_label_set_line_wrap (GTK_LABEL(lab), TRUE);
     gtk_container_add (GTK_CONTAINER (frame), lab);
     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (info_dlg)->vbox),
                         frame, FALSE, FALSE, 0);
+    g_free(container_name);
+
+    frame = gtk_frame_new ("Video");
+    video_num = ply_get_video_num();
+    lab_str = NULL;
+    for (i = 0; i < video_num; i++) {
+        gint video_bitrate = 0;
+        gint width = 0;
+        gint height = 0;
+        gint a_width = 0;
+        gint a_height = 0;
+        gdouble video_framerate = 0.0;
+        gchar * total_info = NULL;
+
+        codec_name = ply_get_video_codec(i);
+        if (!codec_name || !strcmp(codec_name, "")) {
+            show_name = g_strdup_printf("video_%d\n |==== Codec: not known", i);
+        } else {
+            show_name = g_strdup_printf("video_%d\n |==== Codec: %s", i, codec_name);
+        }
+        g_free(codec_name);
+
+        video_bitrate = ply_get_video_bitrate(i);
+
+        video_framerate = ply_get_video_framerate(i);
+
+        ply_get_video_resolution(i, &width, &height);
+
+        ply_get_video_aspectratio(i, &a_width, &a_height);
+
+        total_info = g_strdup_printf("%s,   Bitrate: %d,   FrameRate: %4.2lf,"
+                     "  Resolution: %d X %d   AspectRatio: %d:%d ====|\n",
+                     show_name, video_bitrate, video_framerate, width, height, a_width, a_height);
+        g_free(show_name);
+
+        if (lab_str) {
+            gchar * old = lab_str;
+            lab_str = g_strdup_printf("%s\n%s", old, total_info);
+            g_free(old);
+            g_free(total_info);
+        } else {
+            lab_str = total_info;
+        }
+    }
+
+    lab = gtk_label_new(NULL);
+    gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_LEFT);
+    gtk_label_set_text(GTK_LABEL(lab), lab_str);
+    gtk_label_set_line_wrap (GTK_LABEL(lab), TRUE);
+    gtk_container_add (GTK_CONTAINER (frame), lab);
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (info_dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+    g_free(lab_str);
+
+
+    frame = gtk_frame_new ("Audio");
+    audio_num = ply_get_audio_num();
+    lab_str = NULL;
+    for (i = 0; i < audio_num; i++) {
+        gchar * total_info = NULL;
+        gint audio_bitrate = 0;
+        gint audio_samplerate = 0;
+
+        codec_name = ply_get_audio_codec(i);
+        if (!codec_name || !strcmp(codec_name, "")) {
+            show_name = g_strdup_printf("audio_%d\n |==== Codec: not known", i);
+        } else {
+            show_name = g_strdup_printf("audio_%d\n |==== Codec: %s", i, codec_name);
+        }
+        g_free(codec_name);
+
+        audio_bitrate = ply_get_audio_bitrate(i);
+        audio_samplerate = ply_get_audio_samplerate(i);
+
+        total_info = g_strdup_printf("%s   BitRate: %d   Sample Rate: %d  ====|\n",
+                     show_name, audio_bitrate, audio_samplerate);
+        g_free(show_name);
+
+        if (lab_str) {
+            gchar * old = lab_str;
+            lab_str = g_strdup_printf("%s\n%s", old, total_info);
+            g_free(total_info);
+            g_free(old);
+        } else {
+            lab_str = total_info;
+        }
+    }
+
+    lab = gtk_label_new(NULL);
+    gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_LEFT);
+    gtk_label_set_text(GTK_LABEL(lab), lab_str);
+    gtk_label_set_line_wrap (GTK_LABEL(lab), TRUE);
+    gtk_container_add (GTK_CONTAINER (frame), lab);
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (info_dlg)->vbox),
+                        frame, FALSE, FALSE, 0);
+    g_free(lab_str);
 
     gtk_widget_show_all (info_dlg);
+
+    gtk_dialog_run(GTK_DIALOG(info_dlg));
+    gtk_widget_destroy(info_dlg);
 }
 
 
@@ -197,7 +799,6 @@
         ply_reload_file(filename);
         ui_pause_bt_cb(widget, data);
         g_free(filename);
-        av_sub_update_flag = 1;
     } else {
         gtk_widget_destroy(fileopen_dlg);
     }
@@ -206,44 +807,30 @@
 static void ui_progressbar_vchange_cb( GtkAdjustment *get,
         GtkAdjustment *set )
 {
-    PlyMainData *ply_maindata;
-
-    g_print("fasfafafasfafsa:%f\n", get->value);
     if (ply_get_state() == PLY_MAIN_STATE_RUN ||
          ply_get_state() == PLY_MAIN_STATE_PAUSE) {
-        ply_maindata = ply_get_maindata();
-        ply_seek_stream_from_beginging((get->value / get->upper) * ply_maindata->duration_nanosecond);
+        ply_seek_stream_from_beginging((get->value / get->upper) * ply_get_duration());
     }
 }
 
-void ui_update_channels(void)
+static void ui_volumebar_vchange_cb( GtkAdjustment *get,
+        GtkAdjustment *set )
 {
+    gint volume;
 
-    if (av_sub_update_flag) {
-        GList * c_list = NULL;
-        c_list = g_list_append(c_list, "video0: h264");
-        c_list = g_list_append(c_list, "video1: mpeg2");
-        gtk_combo_set_popdown_strings (GTK_COMBO (video_combo), c_list);
-        g_list_free(c_list);
-
-        c_list = NULL;
-        c_list = g_list_append(c_list, "audio0: AAC");
-        c_list = g_list_append(c_list, "audio1: AC3");
-        gtk_combo_set_popdown_strings (GTK_COMBO (audio_combo), c_list);
-        g_list_free(c_list);
-
-        c_list = NULL;
-        c_list = g_list_append(c_list, "text0");
-        c_list = g_list_append(c_list, "text1");
-        gtk_combo_set_popdown_strings (GTK_COMBO (text_combo), c_list);
-        g_list_free(c_list);
+    if (ply_get_state() == PLY_MAIN_STATE_RUN ||
+         ply_get_state() == PLY_MAIN_STATE_PAUSE) {
+        printf("Volume:  get->value = %d\n", (gint)(get->value));
+        ply_set_volume((gint)get->value);
 
-        av_sub_update_flag = 0;
+        volume = ply_get_volume();
+        //printf("///// The volume now is %d\n", volume);
+        gtk_range_set_value(GTK_RANGE(volume_bar), volume);
+    } else {
+        gtk_range_set_value(GTK_RANGE(volume_bar), 0.0);
     }
 }
 
-
-
 void ui_send_stop_signal(void)
 {
     ui_stop_bt_cb(NULL, NULL);
@@ -254,11 +841,12 @@
     PlyMainData *ply_maindata;
     gchar label_str[30];
 
+    //printf("##### pos = %lld, len = %lld\n", pos, len);
     GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(progressbar));
-    if ( (len / GST_SECOND) != 0) {
-        adj->value = ((pos / GST_SECOND) * 1000) / (len / GST_SECOND);
+    if ( (len) != 0) {
+        adj->value = ((pos) * 1000) / (len);
     }
-    if ( (len / GST_SECOND) == 0 ||
+    if ( (len) == 0 ||
          adj->value > 1000) {
         adj->value = 1000;
         pos = len;
@@ -269,18 +857,62 @@
         adj->value = 0;
     }
 
-    ply_maindata = ply_get_maindata();
-    ply_maindata->duration_nanosecond = len;
+    ply_set_duration(len);
 
     gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
     g_sprintf(label_str, "%02u:%02u:%02u/%02u:%02u:%02u",
-              MY_GST_TIME_ARGS(pos), MY_GST_TIME_ARGS(len));
+              MY_GST_TIME_ARGS(pos*GST_SECOND / 1000), MY_GST_TIME_ARGS(len*GST_SECOND / 1000));
     gtk_label_set_text(GTK_LABEL(progress_time), label_str);
     g_print("%s\n", label_str);
     gtk_widget_show_all(progress_time);
 }
 
 
+static gboolean video_combo_changed(GtkComboBox *comboBox, GtkLabel *label)
+{
+    int video_num = 0;
+    gchar *active = gtk_combo_box_get_active_text(comboBox);
+    //printf("------------ the active is %s\n", active);
+
+    if (active) {
+        sscanf(active, "Video %d:", &video_num);
+        g_free(active);
+    }
+
+    //printf("-------- the number we want to set is %d\n", video_num);
+    ply_set_cur_video(video_num);
+}
+
+static gboolean audio_combo_changed(GtkComboBox *comboBox, GtkLabel *label)
+{
+    int audio_num = 0;
+    gchar *active = gtk_combo_box_get_active_text(comboBox);
+    //printf("------------ the active is %s\n", active);
+
+    if (active) {
+        sscanf(active, "Audio %d:", &audio_num);
+        g_free(active);
+    }
+
+    //printf("-------- the number we want to set is %d\n", audio_num);
+    ply_set_cur_audio(audio_num);
+}
+
+static gboolean text_combo_changed(GtkComboBox *comboBox, GtkLabel *label)
+{
+    int text_num = 0;
+    gchar *active = gtk_combo_box_get_active_text(comboBox);
+    //printf("------------ the active is %s\n", active);
+
+    if (active) {
+        sscanf(active, "Text %d:", &text_num);
+        g_free(active);
+    }
+
+    //printf("-------- the number we want to set is %d\n", text_num);
+}
+
+
 gint ui_create(void)
 {
     GtkWidget *topvbox;
@@ -304,6 +936,7 @@
     GtkWidget *file_menu;
     GtkWidget *play_menu;
     GtkWidget *help_menu;
+    GtkWidget *table;
 
     gtk_widget_show_all(window);
 
@@ -316,6 +949,12 @@
     GtkWidget *progress_hbox;
     progress_hbox = gtk_hbox_new(FALSE, 0);
     gtk_box_pack_start(GTK_BOX(topvbox), progress_hbox, TRUE, TRUE, 0);
+    speed_lab = gtk_label_new(NULL);
+    gtk_label_set_text(GTK_LABEL(speed_lab), "  Play Speed: X 1   ");
+    gtk_label_set_justify(GTK_LABEL(speed_lab), GTK_JUSTIFY_FILL);
+    gtk_label_set_line_wrap (GTK_LABEL(speed_lab), FALSE);
+    gtk_box_pack_start(GTK_BOX(progress_hbox), speed_lab, FALSE, FALSE, 0);
+
     progressbar = gtk_hscale_new_with_range(0, 1000, 1);
     gtk_scale_set_digits(GTK_SCALE(progressbar), 0);
     gtk_scale_set_draw_value(GTK_SCALE(progressbar), FALSE);
@@ -327,26 +966,28 @@
     gtk_box_pack_start(GTK_BOX(progress_hbox), progress_time, FALSE, FALSE, 0);
 
     /* AV/Text streams select and volume */
-    GtkWidget *switch_hbox;
-    switch_hbox = gtk_hbox_new(FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(topvbox), switch_hbox, TRUE, TRUE, 0);
-    GtkWidget *volume_bar;
-
-    video_combo = gtk_combo_new();
-    gtk_combo_set_popdown_strings (GTK_COMBO (video_combo), NULL);
-    gtk_box_pack_start(GTK_BOX(switch_hbox), video_combo, TRUE, TRUE, 0);
-
-    audio_combo = gtk_combo_new();
-    gtk_combo_set_popdown_strings (GTK_COMBO (audio_combo), NULL);
-    gtk_box_pack_start(GTK_BOX(switch_hbox), audio_combo, TRUE, TRUE, 0);
-
-    text_combo = gtk_combo_new();
-    gtk_combo_set_popdown_strings (GTK_COMBO (text_combo), NULL);
-    gtk_box_pack_start(GTK_BOX(switch_hbox), text_combo, TRUE, TRUE, 0);
+    table = gtk_table_new (2, 15, TRUE);
+    gtk_box_pack_start(GTK_BOX(topvbox), table, TRUE, TRUE, 0);
+
+    video_combo = gtk_combo_box_new_text();
+    gtk_table_attach_defaults (GTK_TABLE (table), video_combo, 0, 4, 0, 1);
+    g_signal_connect(GTK_OBJECT(video_combo),
+                     "changed", G_CALLBACK(video_combo_changed), NULL);
+
+    audio_combo = gtk_combo_box_new_text();
+    gtk_table_attach_defaults (GTK_TABLE (table), audio_combo, 4, 8, 0, 1);
+    g_signal_connect(GTK_OBJECT(audio_combo),
+                     "changed", G_CALLBACK(audio_combo_changed), NULL);
+
+    text_combo = gtk_combo_box_new_text();
+    gtk_table_attach_defaults (GTK_TABLE (table), text_combo, 8, 12, 0, 1);
+    g_signal_connect(GTK_OBJECT(text_combo),
+                     "changed", G_CALLBACK(text_combo_changed), NULL);
 
     volume_bar = gtk_hscale_new_with_range(0, 100, 1);
-    gtk_box_pack_start(GTK_BOX(switch_hbox), volume_bar, TRUE, TRUE, 0);
-    gtk_widget_set_size_request(progressbar, 32, 20);
+    adj = gtk_range_get_adjustment(GTK_RANGE(volume_bar));
+    gtk_signal_connect(GTK_OBJECT(adj), "value_changed", GTK_SIGNAL_FUNC(ui_volumebar_vchange_cb), adj);
+    gtk_table_attach_defaults (GTK_TABLE (table), volume_bar, 12, 15, 0, 1);
 
     /* Control Button */
     GtkWidget *button_hbox;
@@ -354,49 +995,85 @@
     GtkWidget *button_stop;
     GtkWidget *button_forward;
     GtkWidget *button_fileopen;
+    GtkWidget *button_uriopen;
+    GtkWidget *button_dvb;
+    GtkWidget *button_subtitle_open;
     GtkWidget *image_rewind;
     GtkWidget *image_stop;
     GtkWidget *image_forward;
     GtkWidget *image_fileopen;
+    GtkWidget *image_uri;
+    GtkWidget *image_info;
     GtkWidget *button_info;
     GtkWidget *button_option;
+    gint v_start = 0;
 
-    button_hbox = gtk_hbox_new(FALSE, 0);
+    //button_hbox = gtk_hbox_new(FALSE, 0);
     gtk_box_pack_start(GTK_BOX(topvbox), button_hbox, FALSE, FALSE, 0);
     button_rewind = gtk_button_new();
     image_rewind = gtk_image_new_from_stock(GTK_STOCK_MEDIA_REWIND, GTK_ICON_SIZE_BUTTON);
     gtk_container_add(GTK_CONTAINER(button_rewind), image_rewind);
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_rewind, TRUE, TRUE, 0);
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_rewind, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_rewind, v_start++, v_start + 1, 1, 2);
+
     button_play = gtk_button_new();
     image_play = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON);
     image_pause = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_BUTTON);
     g_object_ref((gpointer)image_play);
     g_object_ref((gpointer)image_pause);
     gtk_container_add(GTK_CONTAINER(button_play), image_play);
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_play, TRUE, TRUE, 0);
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_play, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_play, v_start++, v_start + 1, 1, 2);
+
     button_stop = gtk_button_new();
     image_stop = gtk_image_new_from_stock(GTK_STOCK_MEDIA_STOP, GTK_ICON_SIZE_BUTTON);
     gtk_container_add(GTK_CONTAINER(button_stop), image_stop);
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_stop, TRUE, TRUE, 0);
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_stop, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_stop, v_start++, v_start + 1, 1, 2);
+
     button_forward = gtk_button_new();
     image_forward = gtk_image_new_from_stock(GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_BUTTON);
     gtk_container_add(GTK_CONTAINER(button_forward), image_forward);
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_forward, TRUE, TRUE, 0);
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_forward, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_forward, v_start++, v_start + 1, 1, 2);
+
     button_fileopen = gtk_button_new();
     image_fileopen = gtk_image_new_from_stock("gtk-open", GTK_ICON_SIZE_BUTTON);
     gtk_container_add(GTK_CONTAINER(button_fileopen), image_fileopen);
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_fileopen, TRUE, TRUE, 0);
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_fileopen, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_fileopen, v_start++, v_start + 1, 1, 2);
+
+    button_uriopen = gtk_button_new();
+    image_uri = gtk_image_new_from_stock("gtk-file", GTK_ICON_SIZE_BUTTON);
+    gtk_container_add(GTK_CONTAINER(button_uriopen), image_uri);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_uriopen, v_start++, v_start + 1, 1, 2);
+
+    button_subtitle_open = gtk_button_new_with_label("Sub");
+    gtk_table_attach_defaults (GTK_TABLE (table), button_subtitle_open, v_start++, v_start + 1, 1, 2);
+
+    button_dvb = gtk_button_new_with_label("DVB");
+    gtk_table_attach_defaults (GTK_TABLE (table), button_dvb, v_start++, v_start + 1, 1, 2);
 
     g_signal_connect((gpointer)button_fileopen, "clicked", G_CALLBACK(ui_fileopen_dlg), NULL);
     g_signal_connect((gpointer)button_play, "clicked", G_CALLBACK(ui_pause_bt_cb), NULL);
     g_signal_connect((gpointer)button_stop, "clicked", G_CALLBACK(ui_stop_bt_cb), NULL);
     g_signal_connect((gpointer)button_rewind, "clicked", G_CALLBACK(ui_rewind_bt_cb), NULL);
     g_signal_connect((gpointer)button_forward, "clicked", G_CALLBACK(ui_forward_bt_cb), NULL);
+    g_signal_connect((gpointer)button_uriopen, "clicked", G_CALLBACK(ui_uri_open_bt_cb), NULL);
+    g_signal_connect((gpointer)button_subtitle_open, "clicked", G_CALLBACK(ui_sub_open_bt_cb), NULL);
+    g_signal_connect((gpointer)button_dvb, "clicked", G_CALLBACK(ui_dvb_bt_cb), NULL);
+
+    button_info = gtk_button_new();
+    image_info = gtk_image_new_from_stock("gtk-info", GTK_ICON_SIZE_BUTTON);
+    gtk_container_add(GTK_CONTAINER(button_info), image_info);
 
-    button_info = gtk_button_new_with_label("Info");
     button_option = gtk_button_new_with_label("Options");
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_info, TRUE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(button_hbox), button_option, TRUE, TRUE, 0);
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_info, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_info, v_start, v_start + 2, 1, 2);
+    v_start += 2;
+    //gtk_box_pack_start(GTK_BOX(button_hbox), button_option, TRUE, TRUE, 0);
+    gtk_table_attach_defaults (GTK_TABLE (table), button_option, v_start, v_start + 2, 1, 2);
+    v_start += 2;
     g_signal_connect((gpointer)button_info, "clicked", G_CALLBACK(ui_info_bt_cb), NULL);
     g_signal_connect((gpointer)button_option, "clicked", G_CALLBACK(ui_options_bt_cb), NULL);
 
--- test/ui/umms-gtk-ui.h
+++ test/ui/umms-gtk-ui.h
@@ -25,6 +25,22 @@
 #define UI_H_
 #include <gtk/gtk.h>
 
+typedef enum _UI_CALLBACK_REASONS 
+{
+    UI_CALLBACK_STATE_CHANGE,
+    UI_CALLBACK_EOF,
+    UI_CALLBACK_SEEKED,
+    UI_CALLBACK_BUFFERING,
+    UI_CALLBACK_BUFFERED,
+    UI_CALLBACK_VIDEO_TAG_CHANGED,
+    UI_CALLBACK_AUDIO_TAG_CHANGED,
+    UI_CALLBACK_TEXT_TAG_CHANGED,
+    UI_CALLBACK_STOPPED,
+    UI_CALLBACK_ERROR,
+
+}UI_CALLBACK_REASONS;
+
+
 extern GtkWidget *video_window;
 extern GtkWidget *window;
 
@@ -51,5 +67,6 @@
 void ui_update_progressbar(gint64 pos, gint64 len);
 void ui_update_channels(void);
 
+void ui_callbacks_for_reason(UI_CALLBACK_REASONS reason, void * data1, void * data2);
 
 #endif /* UI_H_ */



More information about the MeeGo-commits mailing list