[maemo-commits] [maemo-commits] r17865 - projects/haf/trunk/hildon-welcome/src

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Mon Mar 30 15:13:58 EEST 2009
Author: schulhof
Date: 2009-03-30 15:13:55 +0300 (Mon, 30 Mar 2009)
New Revision: 17865

Modified:
   projects/haf/trunk/hildon-welcome/src/main.c
Log:
Absolute timeout is not fatal

Modified: projects/haf/trunk/hildon-welcome/src/main.c
===================================================================
--- projects/haf/trunk/hildon-welcome/src/main.c	2009-03-30 12:00:26 UTC (rev 17864)
+++ projects/haf/trunk/hildon-welcome/src/main.c	2009-03-30 12:13:55 UTC (rev 17865)
@@ -34,6 +34,8 @@
 #endif /* HAVE_MCE */
 #include "conffile.h"
 
+#define KILL_TO_LENGTH_MS 30000
+
 #define DEFAULT_VIDEO_PIPELINE_STR " playbin2 uri=file://%s " /* " flags=99 " <-- doesn't work with still images */
 #define DEFAULT_AUDIO_PIPELINE_STR " filesrc location=%s ! decodebin2 ! autoaudiosink "
 #define DEFAULT_SHUSH_PIPELINE_STR " audiotestsrc ! volume volume=0 ! autoaudiosink "
@@ -41,34 +43,184 @@
 static char *video_pipeline_str = DEFAULT_VIDEO_PIPELINE_STR;
 static char *audio_pipeline_str = DEFAULT_AUDIO_PIPELINE_STR;
 static char *shush_pipeline_str = DEFAULT_SHUSH_PIPELINE_STR;
+static GTimer *global_timer = NULL;
 
+typedef struct
+{
+  GTimer *timer;
+  guint to_ms;
+  GstElement *pipeline;
+  guint timeout_id;
+  const char *warning;
+} TimeoutParams;
+
+static gboolean
+post_eos(TimeoutParams *tp)
+{
+  if (tp->timer) {
+    double diff_ms = ((double)(tp->to_ms)) - (g_timer_elapsed(tp->timer, NULL) * 1000.0);
+    if (diff_ms > 0) {
+      g_warning("[%lf]: post_eos: False alarm! %lf ms () left\n", g_timer_elapsed(global_timer, NULL), diff_ms);
+      tp->timeout_id = g_timeout_add((guint)diff_ms, (GSourceFunc)post_eos, tp);
+      return FALSE;
+    }
+  }
+  if (tp->warning)
+    g_warning("[%lf]: post_eos: %s", g_timer_elapsed(global_timer, NULL), tp->warning);
+  gst_bus_post(gst_pipeline_get_bus(GST_PIPELINE(tp->pipeline)), gst_message_new_eos(GST_OBJECT(tp->pipeline)));
+
+  tp->timeout_id = 0;
+  if (tp->timer) {
+    g_timer_destroy(tp->timer);
+    tp->timer = NULL;
+  }
+  return FALSE;
+}
+
 static void
-my_log_func(const gchar *log_domain, GLogLevelFlags log_level, const char *message, gpointer null)
+post_eos_timeout_add(guint to_ms, GstElement *pipeline, char *warning, TimeoutParams *params)
 {
-  char *new_msg = NULL;
-  static GTimer *timer = NULL;
+  params->to_ms = to_ms;
+  params->pipeline = pipeline;
+  params->warning = warning;
+  params->timer = g_timer_new();
+  params->timeout_id = g_timeout_add(to_ms, (GSourceFunc)post_eos, params);
+}
 
-  if (G_UNLIKELY(!timer))
-    timer = g_timer_new();
+static void
+post_eos_timeout_remove(TimeoutParams *params)
+{
+  if (params->timeout_id) {
+    g_source_remove(params->timeout_id);
+    params->timeout_id = 0;
+  }
+  if (params->timer) {
+    g_timer_destroy(params->timer);
+    params->timer = NULL;
+  }
+}
 
-  new_msg = g_strdup_printf("[%lf]: %s", timer ? g_timer_elapsed(timer, NULL) : G_MAXDOUBLE, message);
-  g_log_default_handler (log_domain, log_level, (const char *)new_msg, NULL);
-  g_free(new_msg);
+static void
+wait_for_eos(GstElement *pipeline, Window dst_window, int duration, TimeoutParams *play_to)
+{
+  GError *err = NULL;
+  char *debug = NULL;
+  gboolean keep_looping = TRUE;
+  GstMessage *message = NULL;
+
+  while (keep_looping) {
+    message = gst_bus_poll(gst_pipeline_get_bus(GST_PIPELINE(pipeline)), GST_MESSAGE_ANY, -1);
+    if (!message) break;
+
+    switch(GST_MESSAGE_TYPE(message)) {
+      case GST_MESSAGE_ASYNC_DONE:
+        g_debug("[%lf]: wait_for_eos: Ready to play: duration = %d\n", g_timer_elapsed(global_timer, NULL), duration);
+        if ((duration > 500) && !(play_to->timeout_id))
+          post_eos_timeout_add(duration, pipeline, NULL, play_to);
+        break;
+
+      case GST_MESSAGE_ERROR:
+        gst_message_parse_error(message, &err, &debug);
+        g_warning("[%lf]: wait_for_eos: %s: %s %s\n", g_timer_elapsed(global_timer, NULL), GST_MESSAGE_TYPE_NAME(message), err ? err->message : "", debug ? debug : "");
+        if (err)
+          g_error_free(err);
+        g_free(debug);
+        /* fall through */
+      case GST_MESSAGE_EOS:
+        keep_looping = FALSE;
+        gst_element_set_state(pipeline, GST_STATE_PAUSED);
+        g_debug("[%lf]: wait_for_eos: Gst message: %s", g_timer_elapsed(global_timer, NULL), GST_MESSAGE_TYPE_NAME(message));
+        break;
+
+      case GST_MESSAGE_ELEMENT:
+        if (gst_structure_has_name(message->structure, "prepare-xwindow-id"))
+          gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), dst_window);
+        break;
+
+      default:
+        break;
+    }
+    gst_message_unref(message);
+  }
 }
 
+static void
+unblank_screen()
+{
+#ifdef HAVE_MCE
+  DBusConnection *conn = NULL;
+
+  if ((conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL)) != NULL) {
+    DBusMessage *message, *reply;
+
+    if ((message = dbus_message_new_method_call(MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF, MCE_DISPLAY_ON_REQ)) != NULL) {
+      if ((reply = dbus_connection_send_with_reply_and_block(conn, message, -1, NULL)) != NULL)
+        dbus_message_unref(reply);
+      dbus_message_unref(message);
+    }
+  }
+#endif /* HAVE_MCE */
+}
+
 static GstElement *
-create_pipeline(GstElement **p_audio_bin, GstElement **p_video_bin, GstElement **p_shush_bin)
+play_logo(Window dst_window, char *video, char *audio, int duration)
 {
-  GstElement *pipeline = NULL;
+  GstElement* pipeline = NULL;
+  GString *pipeline_str = g_string_new("");
 
-  pipeline = gst_pipeline_new();
+  g_debug("[%lf]: play_logo: playing (video = '%s', audio = '%s', duration = '%d')", g_timer_elapsed(global_timer, NULL), video, audio, duration);
 
-  (*p_audio_bin) = gst_element_make("playbin2", "audio_bin");
-  (*p_video_bin) = gst_element_make("playbin2", "video_bin");
+  if (video && video[0])
+    g_string_append_printf(pipeline_str, video_pipeline_str, video);
 
+  if (audio && audio[0]) {
+    if ('s' == audio[0] && 0 == audio[1])
+      g_string_append_printf(pipeline_str, shush_pipeline_str);
+    else
+      g_string_append_printf(pipeline_str, audio_pipeline_str, audio);
+  }
+
+  pipeline = gst_parse_launch(pipeline_str->str, NULL);
+  g_string_free(pipeline_str, TRUE);
+
+  if (pipeline) {
+    TimeoutParams kill_to, play_to;
+
+    post_eos_timeout_add(KILL_TO_LENGTH_MS, pipeline, "Absolute timeout reached!\n", &kill_to);
+
+    gst_element_set_state(pipeline, GST_STATE_PLAYING);
+    unblank_screen();
+    wait_for_eos(pipeline, dst_window, duration, &play_to);
+
+    post_eos_timeout_remove(&kill_to);
+    post_eos_timeout_remove(&play_to);
+  }
+
   return pipeline;
 }
 
+/* Paint a black filled rectangle over the given window */
+static void
+draw_black(Display *dpy, Window dst_window)
+{
+  XGCValues vals;
+  Window root_window;
+  int x, y;
+  unsigned int cx, cy, cx_border, depth;
+
+  if (!XGetGeometry(dpy, dst_window, &root_window, &x, &y, &cx, &cy, &cx_border, &depth)) {
+     x =   0;  y =   0;
+    cx = 800; cy = 480;
+  }
+
+  vals.foreground = BlackPixel(dpy, 0);
+  vals.background = BlackPixel(dpy, 0);
+  GC gc = XCreateGC(dpy, dst_window, GCForeground | GCBackground, &vals);
+  XFillRectangle(dpy, dst_window, gc, x, y, cx, cy);
+  XFreeGC(dpy, gc);
+  XFlush(dpy);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -110,11 +262,10 @@
   int duration;
   ConfFileIterator *itr;
   Window dst_window = 0, xcomposite_window = 0;
+  GstElement *new_pipeline = NULL, *old_pipeline = NULL;
 
   if (!g_thread_supported ()) g_thread_init(NULL);
 
-  g_log_set_default_handler(my_log_func, NULL);
-
   ctx = g_option_context_new(NULL);
   g_option_context_add_main_entries (ctx, options, NULL);
   g_option_context_add_group (ctx, gst_init_get_option_group());
@@ -124,24 +275,36 @@
 
   gst_init(&argc, &argv);
 
+  global_timer = g_timer_new();
+
   if (!(display = XOpenDisplay(NULL)))
-    g_error("main: Failed to open display\n");
+    g_error("[%lf]: main: Failed to open display\n", g_timer_elapsed(global_timer, NULL));
   if ((dst_window = DefaultRootWindow(display)) == 0)
-    g_error("main: Failed to obtain root window\n");
+    g_error("[%lf]: Failed to obtain root window\n", g_timer_elapsed(global_timer, NULL));
 
   if ((xcomposite_window = XCompositeGetOverlayWindow(display, dst_window)) != 0)
     dst_window = xcomposite_window;
 
   if ((itr = conf_file_iterator_new())) {
     while (conf_file_iterator_get(itr, &video, &audio, &duration)) {
-      g_debug("main: video = %s, audio = %s, duration = %d\n", video, audio, duration);
+      new_pipeline = play_logo(dst_window, video, audio, duration);
       g_free(video); video = NULL;
       g_free(audio); audio = NULL;
       duration = 0;
+      if (old_pipeline) {
+        gst_element_set_state(old_pipeline, GST_STATE_NULL);
+        gst_object_unref(old_pipeline);
+      }
+      old_pipeline = new_pipeline;
     }
     conf_file_iterator_destroy(itr);
   }
 
+  /* Prevent the green flash before the application quits */
+  draw_black(display, dst_window);
+  gst_element_set_state(new_pipeline, GST_STATE_NULL);
+  gst_object_unref(new_pipeline);
+
   if (xcomposite_window)
     XCompositeReleaseOverlayWindow(display, xcomposite_window);
 
@@ -149,5 +312,7 @@
 
   gst_deinit();
 
+  g_timer_destroy(global_timer);
+
   return 0;
 }


More information about the maemo-commits mailing list