[telepathy-stream-engine/master] Switch Xv adapter depending on TV-out status

Olivier Crête olivier.crete at collabora.co.uk
Thu Dec 17 09:19:21 PST 2009


---
 src/tp-stream-engine.c |  168 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 168 insertions(+), 0 deletions(-)

diff --git a/src/tp-stream-engine.c b/src/tp-stream-engine.c
index 0b65393..e4d787b 100644
--- a/src/tp-stream-engine.c
+++ b/src/tp-stream-engine.c
@@ -29,6 +29,7 @@
 #include <netinet/ip.h>
 
 #include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
 
 #include <libhal.h>
 
@@ -55,6 +56,9 @@
 #define BUS_NAME        "org.maemo.Telepathy.StreamEngine"
 #define OBJECT_PATH     "/org/maemo/Telepathy/StreamEngine"
 
+#define VIDEO_JACK_UDI   "/org/freedesktop/Hal/devices/platform_soc_audio_logicaldev_input"
+#define VIDEO_JACK_PROPERTY  "input.jack.type"
+
 static void
 _create_pipeline (TpStreamEngine *self);
 
@@ -166,6 +170,11 @@ struct _TpStreamEnginePrivate
   GPtrArray *audio_objects;
 
   GHashTable *object_threads;
+
+  DBusGConnection *system_bus_connection;
+  LibHalContext *libhal_ctx;
+
+  gboolean has_tv_out;
 };
 
 static void
@@ -354,6 +363,18 @@ tp_stream_engine_dispose (GObject *object)
   if (priv->dispose_has_run)
     return;
 
+  if (self->priv->libhal_ctx)
+    {
+      libhal_ctx_shutdown (self->priv->libhal_ctx, NULL);
+      libhal_ctx_free (self->priv->libhal_ctx);
+      self->priv->libhal_ctx = NULL;
+    }
+
+  if (self->priv->system_bus_connection)
+    {
+      dbus_g_connection_unref (self->priv->system_bus_connection);
+      self->priv->system_bus_connection = NULL;
+    }
 
   if (self->priv->reset_failcount_id)
     {
@@ -1514,6 +1535,14 @@ preview_size_changed (TpStreamEngineVideoPreview *videopreview,
 }
 
 
+static void
+set_xv_device (TpStreamEngineVideoPreview *preview, gboolean has_tvout)
+{
+  gchar *device = has_tvout ? "1" : "0";
+
+  g_object_set (preview, "xv-device", device, NULL);
+}
+
 /**
  * tp_stream_engine_create_preview_window
  *
@@ -1540,6 +1569,8 @@ tp_stream_engine_create_preview_window (StreamEngineSvcStreamEngine *iface,
       return;
     }
 
+  set_xv_device (preview, self->priv->has_tv_out);
+
   g_mutex_lock (self->priv->mutex);
   self->priv->preview_sinks = g_list_prepend (self->priv->preview_sinks,
       preview);
@@ -1604,6 +1635,7 @@ tp_stream_engine_get_preview_window (StreamEngineSvcStreamEngine *iface,
       return;
     }
 
+  set_xv_device (preview, self->priv->has_tv_out);
 
   g_mutex_lock (self->priv->mutex);
   self->priv->preview = preview;
@@ -1749,6 +1781,140 @@ tp_stream_engine_attach_to_channel (StreamEngineSvcStreamEngine *iface,
   g_signal_emit (self, signals[HANDLING_CHANNEL], 0);
 }
 
+static gboolean
+has_tvout (TpStreamEngine *self)
+{
+  char **values = NULL;
+  int i;
+  DBusError error;
+  gboolean has_video = FALSE;
+
+
+  dbus_error_init (&error);
+
+  values = libhal_device_get_property_strlist (self->priv->libhal_ctx,
+      VIDEO_JACK_UDI, VIDEO_JACK_PROPERTY, NULL);
+
+  if (dbus_error_is_set (&error))
+    {
+      g_warning ("Could not get property list for %s:%s: %s",
+          VIDEO_JACK_UDI, VIDEO_JACK_PROPERTY, error.message);
+      dbus_error_free (&error);
+      return;
+    }
+
+  if (values)
+    {
+      for (i = 0; values[i]; i++)
+        {
+          if (!strcmp ("video-out", values[i]))
+            {
+              has_video = TRUE;
+              break;
+            }
+        }
+    }
+  g_strfreev (values);
+
+  return has_video;
+}
+
+static void
+libhal_property_modified (LibHalContext *ctx,
+    const char *udi,
+    const char *key,
+    dbus_bool_t is_removed,
+    dbus_bool_t is_added)
+{
+  TpStreamEngine *self = libhal_ctx_get_user_data (ctx);
+  gboolean has_tv_out_new;
+
+  if (strcmp (udi, VIDEO_JACK_UDI) || strcmp (key, VIDEO_JACK_PROPERTY))
+    return;
+
+  has_tv_out_new = has_tvout (self);
+
+  if (has_tv_out_new != self->priv->has_tv_out)
+    {
+      GList *item;
+
+      g_debug ("TV out %s, switching preview's Xv adapter",
+          has_tv_out_new ? "enabled" : "disabled");
+
+      self->priv->has_tv_out = has_tv_out_new;
+
+      g_mutex_lock (self->priv->mutex);
+      if (self->priv->preview)
+        set_xv_device (self->priv->preview, has_tv_out_new);
+
+      for (item = self->priv->preview_sinks; item; item = g_list_next (item))
+        set_xv_device (item->data, has_tv_out_new);
+      g_mutex_unlock (self->priv->mutex);
+    }
+}
+
+static void
+setup_hal (TpStreamEngine *self)
+{
+  DBusError error;
+  GError *gerror = NULL;
+
+  dbus_error_init (&error);
+  self->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM,
+      &gerror);
+  if (!self->priv->system_bus_connection)
+    {
+        g_error ("Unable to connect to DBus: %s", gerror->message);
+        g_clear_error (&gerror);
+        return;
+    }
+
+  self->priv->libhal_ctx = libhal_ctx_new ();
+
+  if (!libhal_ctx_set_dbus_connection (self->priv->libhal_ctx,
+          dbus_g_connection_get_connection (
+              self->priv->system_bus_connection)))
+    {
+      g_error ("Error setting dbus connection on hal ctx: %s", error.message);
+      dbus_error_free (&error);
+      return;
+    }
+
+  if (!libhal_ctx_init (self->priv->libhal_ctx, &error))
+    {
+      g_error ("Hal context initializing failure %s", error.message);
+      dbus_error_free (&error);
+      return;
+    }
+
+  libhal_ctx_set_user_data (self->priv->libhal_ctx, self);
+
+  libhal_ctx_set_device_property_modified (self->priv->libhal_ctx,
+      libhal_property_modified);
+
+
+  if (libhal_device_exists (self->priv->libhal_ctx, VIDEO_JACK_UDI, &error))
+    {
+      if (!libhal_device_add_property_watch (self->priv->libhal_ctx,
+              VIDEO_JACK_UDI, &error))
+        {
+          g_warning ("Could not add property watch: %s", error.message);
+          dbus_error_free (&error);
+          return;
+        }
+
+      self->priv->has_tv_out = has_tvout (self);
+    }
+  else
+    {
+      g_warning ("No video jack found: Video out support disabled: %s",
+          error.message);
+      dbus_error_free (&error);
+      return;
+    }
+
+}
+
 void
 tp_stream_engine_register (TpStreamEngine *self)
 {
@@ -1775,6 +1941,8 @@ tp_stream_engine_register (TpStreamEngine *self)
 
   if (request_name_result == DBUS_REQUEST_NAME_REPLY_EXISTS)
     g_error ("Failed to acquire bus name, stream engine already running?");
+
+  setup_hal (self);
 }
 
 static TfStream *
-- 
1.5.6.5



More information about the telepathy-commits mailing list