[gnome-online-accounts] Add Media Server



commit 2b0b19305fc7141999e0050db301cfbae347a3e7
Author: Pranav Kant <pranav913 gmail com>
Date:   Tue Jun 3 17:13:24 2014 +0530

    Add Media Server
    
    https://bugzilla.gnome.org/show_bug.cgi?id=730890

 configure.ac                            |   12 +
 doc/goa-docs.xml                        |    1 +
 doc/goa-sections.txt                    |   10 +
 doc/goa.types                           |    1 +
 po/POTFILES.in                          |    1 +
 src/goabackend/Makefile.am              |    2 +
 src/goabackend/goadlnaservermanager.c   |  266 +++++++++++++
 src/goabackend/goadlnaservermanager.h   |   71 ++++
 src/goabackend/goamediaserverprovider.c |  624 +++++++++++++++++++++++++++++++
 src/goabackend/goamediaserverprovider.h |   40 ++
 src/goabackend/goaprovider.c            |    4 +
 11 files changed, 1032 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5f68667..29921ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -225,6 +225,17 @@ if test "$enable_imap_smtp" != "no"; then
   AC_DEFINE(GOA_IMAP_SMTP_ENABLED, 1, [Enable IMAP/SMTP data provider])
 fi
 
+# Media Server
+AC_DEFINE(GOA_MEDIA_SERVER_NAME, ["media_server"], [ProviderType and extension point name])
+AC_ARG_ENABLE([media-server],
+              [AS_HELP_STRING([--enable-media-server],
+              [Enable Media Server provider])],
+              [],
+              [enable_media_server=no])
+if test "$enable_media_server" != "no"; then
+  AC_DEFINE(GOA_MEDIA_SERVER_ENABLED, 1, [Enable Media Server provider])
+fi
+
 # ownCloud
 AC_DEFINE(GOA_OWNCLOUD_NAME, ["owncloud"], [ProviderType and extension point name])
 AC_ARG_ENABLE([owncloud],
@@ -521,6 +532,7 @@ echo "
        Flickr provider:                ${enable_flickr} (OAuth 1.0, key:${with_flickr_consumer_key} 
secret:${with_flickr_consumer_secret})
        Google provider:                ${enable_google} (OAuth 2.0, id:${with_google_client_id} 
secret:${with_google_client_secret})
        IMAP/SMTP provider:             ${enable_imap_smtp}
+       Media Server provider:          ${enable_media_server}
        Microsoft Exchange provider:    ${enable_exchange}
        ownCloud provider:              ${enable_owncloud}
        Kerberos provider:              ${enable_kerberos}
diff --git a/doc/goa-docs.xml b/doc/goa-docs.xml
index 617beb1..b980c03 100644
--- a/doc/goa-docs.xml
+++ b/doc/goa-docs.xml
@@ -172,6 +172,7 @@
       <title>Providers</title>
       <xi:include href="xml/goaexchangeprovider.xml"/>
       <xi:include href="xml/goagoogleprovider.xml"/>
+      <xi:include href="xml/goamediaserverprovider.xml"/>
       <xi:include href="xml/goawindowsliveprovider.xml"/>
       <xi:include href="xml/goafacebookprovider.xml"/>
       <xi:include href="xml/goayahooprovider.xml"/>
diff --git a/doc/goa-sections.txt b/doc/goa-sections.txt
index 351e664..fc6f0f0 100644
--- a/doc/goa-sections.txt
+++ b/doc/goa-sections.txt
@@ -542,6 +542,16 @@ goa_exchange_provider_get_type
 </SECTION>
 
 <SECTION>
+<FILE>goamediaserverprovider</FILE>
+GoaMediaServerProvider
+<SUBSECTION Standard>
+GOA_MEDIA_SERVER_PROVIDER
+GOA_IS_MEDIA_SERVER_PROVIDER
+GOA_TYPE_MEDIA_SERVER_PROVIDER
+goa_media_server_provider_get_type
+</SECTION>
+
+<SECTION>
 <FILE>goagoogleprovider</FILE>
 GoaGoogleProvider
 <SUBSECTION Standard>
diff --git a/doc/goa.types b/doc/goa.types
index c88c0af..ffb85b4 100644
--- a/doc/goa.types
+++ b/doc/goa.types
@@ -32,6 +32,7 @@ goa_oauth_provider_get_type
 goa_oauth2_provider_get_type
 goa_google_provider_get_type
 goa_facebook_provider_get_type
+goa_media_server_provider_get_type
 goa_yahoo_provider_get_type
 goa_flickr_provider_get_type
 goa_windows_live_provider_get_type
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 988aadf..32b4688 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ src/goabackend/goahttpclient.c
 src/goabackend/goaimapauthlogin.c
 src/goabackend/goaimapsmtpprovider.c
 src/goabackend/goakerberosprovider.c
+src/goabackend/goamediaserverprovider.c
 src/goabackend/goaoauth2provider.c
 src/goabackend/goaoauthprovider.c
 src/goabackend/goaowncloudprovider.c
diff --git a/src/goabackend/Makefile.am b/src/goabackend/Makefile.am
index 38a4f8d..f3b87f1 100644
--- a/src/goabackend/Makefile.am
+++ b/src/goabackend/Makefile.am
@@ -69,6 +69,7 @@ libgoa_backend_1_0_la_SOURCES =                                               \
        goabackendtypes.h                                               \
        goabackendenums-priv.h                                          \
        goabackendenumtypes.h           goabackendenumtypes.c           \
+       goadlnaservermanager.h          goadlnaservermanager.c          \
        goaewsclient.h                  goaewsclient.c                  \
        goahttpclient.h                 goahttpclient.c                 \
        goaprovider-priv.h              goaprovider.c                   \
@@ -83,6 +84,7 @@ libgoa_backend_1_0_la_SOURCES =                                               \
        goagoogleprovider.h             goagoogleprovider.c             \
        goafacebookprovider.h           goafacebookprovider.c           \
        goaimapsmtpprovider.h           goaimapsmtpprovider.c           \
+       goamediaserverprovider.h        goamediaserverprovider.c        \
        goaowncloudprovider.h           goaowncloudprovider.c           \
        goayahooprovider.h              goayahooprovider.c              \
        goaflickrprovider.h             goaflickrprovider.c             \
diff --git a/src/goabackend/goadlnaservermanager.c b/src/goabackend/goadlnaservermanager.c
new file mode 100644
index 0000000..cb2d7b1
--- /dev/null
+++ b/src/goabackend/goadlnaservermanager.c
@@ -0,0 +1,266 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2014 Pranav Kant
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "goadleynaservermanager.h"
+#include "goadleynaservermediadevice.h"
+#include "goadlnaservermanager.h"
+
+struct _GoaDlnaServerManagerPrivate
+{
+  DleynaServerManager *proxy;
+  GHashTable *servers;
+};
+
+enum
+{
+  SERVER_FOUND,
+  SERVER_LOST,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GoaDlnaServerManager, goa_dlna_server_manager, G_TYPE_OBJECT);
+
+static GObject *goa_dlna_server_manager_singleton = NULL;
+
+static void
+goa_dlna_server_manager_server_new_cb (GObject      *source_object,
+                                       GAsyncResult *res,
+                                       gpointer      user_data)
+{
+  GoaDlnaServerManager *self = GOA_DLNA_SERVER_MANAGER (user_data);
+  GoaDlnaServerManagerPrivate *priv = self->priv;
+  DleynaServerMediaDevice *server;
+  GError *error = NULL;
+  const gchar *object_path;
+
+  server = dleyna_server_media_device_proxy_new_for_bus_finish (res, &error);
+  if (error != NULL)
+    {
+      g_warning ("Unable to load server object: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (server));
+
+  g_debug ("%s '%s' %s %s",
+           G_STRFUNC,
+           dleyna_server_media_device_get_friendly_name (server),
+           dleyna_server_media_device_get_udn (server),
+           object_path);
+  g_hash_table_insert (priv->servers, (gpointer) object_path, server);
+  g_signal_emit (self, signals[SERVER_FOUND], 0, server);
+
+ out:
+  g_object_unref (self);
+}
+
+static void
+goa_dlna_server_manager_server_found_cb (GoaDlnaServerManager *self,
+                                         const gchar *object_path,
+                                         gpointer *data)
+{
+  dleyna_server_media_device_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                                G_DBUS_PROXY_FLAGS_NONE,
+                                                "com.intel.dleyna-server",
+                                                object_path,
+                                                NULL, /* GCancellable */
+                                                goa_dlna_server_manager_server_new_cb,
+                                                g_object_ref (self));
+}
+
+static void
+goa_dlna_server_manager_server_lost_cb (GoaDlnaServerManager *self,
+                                        const gchar *object_path,
+                                        gpointer *data)
+{
+  GoaDlnaServerManagerPrivate *priv = self->priv;
+  DleynaServerMediaDevice *server;
+
+  server = DLEYNA_SERVER_MEDIA_DEVICE (g_hash_table_lookup (priv->servers, object_path));
+  g_return_if_fail (server != NULL);
+
+  g_hash_table_steal (priv->servers, object_path);
+  g_debug ("%s '%s' %s %s",
+           G_STRFUNC,
+           dleyna_server_media_device_get_friendly_name (server),
+           dleyna_server_media_device_get_udn (server),
+           object_path);
+  g_signal_emit (self, signals[SERVER_LOST], 0, server);
+  g_object_unref (server);
+}
+
+static void
+goa_dlna_server_manager_proxy_get_servers_cb (GObject      *source_object,
+                                              GAsyncResult *res,
+                                              gpointer      user_data)
+{
+  GoaDlnaServerManager *self = GOA_DLNA_SERVER_MANAGER (user_data);
+  GoaDlnaServerManagerPrivate *priv = self->priv;
+  GError *error = NULL;
+  gchar **object_paths = NULL;
+  guint i;
+
+  dleyna_server_manager_call_get_servers_finish (priv->proxy, &object_paths, res, &error);
+  if (error != NULL)
+    {
+      g_warning ("Unable to fetch the list of available servers: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  for (i = 0; object_paths[i] != NULL; i++)
+    goa_dlna_server_manager_server_found_cb (self, object_paths[i], NULL);
+
+  g_signal_connect_swapped (priv->proxy, "found-server", G_CALLBACK 
(goa_dlna_server_manager_server_found_cb), self);
+  g_signal_connect_swapped (priv->proxy, "lost-server", G_CALLBACK (goa_dlna_server_manager_server_lost_cb), 
self);
+
+ out:
+  g_strfreev (object_paths);
+  g_object_unref (self);
+}
+
+static void
+goa_dlna_server_manager_proxy_new_cb (GObject *source_object,
+                                      GAsyncResult *res,
+                                      gpointer user_data)
+{
+  GoaDlnaServerManager *self = GOA_DLNA_SERVER_MANAGER (user_data);
+  GoaDlnaServerManagerPrivate *priv = self->priv;
+  GError *error = NULL;
+
+  priv->proxy = dleyna_server_manager_proxy_new_for_bus_finish (res, &error);
+  if (error != NULL)
+    {
+      g_warning ("Unable to connect to the dLeynaServer.Manager DBus object: %s",
+                 error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  g_debug ("%s DLNA server manager initialized", G_STRFUNC);
+
+  dleyna_server_manager_call_get_servers (priv->proxy,
+                                          NULL,
+                                          goa_dlna_server_manager_proxy_get_servers_cb,
+                                          g_object_ref (self));
+
+ out:
+  g_object_unref (self);
+}
+
+static void
+goa_dlna_server_manager_dispose (GObject *object)
+{
+  GoaDlnaServerManager *self = GOA_DLNA_SERVER_MANAGER (object);
+  GoaDlnaServerManagerPrivate *priv = self->priv;
+
+  g_clear_pointer (&priv->servers, (GDestroyNotify) g_hash_table_unref);
+  g_clear_object (&priv->proxy);
+
+  G_OBJECT_CLASS (goa_dlna_server_manager_parent_class)->dispose (object);
+}
+
+static GObject *
+goa_dlna_server_manager_constructor (GType type,
+                                     guint n_construct_params,
+                                     GObjectConstructParam *construct_params)
+{
+  if (goa_dlna_server_manager_singleton == NULL)
+    {
+      goa_dlna_server_manager_singleton =
+        G_OBJECT_CLASS (goa_dlna_server_manager_parent_class)->constructor (type,
+                                                                            n_construct_params,
+                                                                            construct_params);
+      g_object_add_weak_pointer (goa_dlna_server_manager_singleton,
+                                 (gpointer) &goa_dlna_server_manager_singleton);
+      return goa_dlna_server_manager_singleton;
+    }
+
+  return g_object_ref (goa_dlna_server_manager_singleton);
+}
+
+static void
+goa_dlna_server_manager_init (GoaDlnaServerManager *self)
+{
+  GoaDlnaServerManagerPrivate *priv;
+
+  self->priv = priv = goa_dlna_server_manager_get_instance_private (self);
+  dleyna_server_manager_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                           G_DBUS_PROXY_FLAGS_NONE,
+                                           "com.intel.dleyna-server",
+                                           "/com/intel/dLeynaServer",
+                                           NULL, /* GCancellable */
+                                           goa_dlna_server_manager_proxy_new_cb,
+                                           g_object_ref (self));
+  priv->servers = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+}
+
+static void
+goa_dlna_server_manager_class_init (GoaDlnaServerManagerClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->constructor = goa_dlna_server_manager_constructor;
+  object_class->dispose = goa_dlna_server_manager_dispose;
+
+  signals[SERVER_FOUND] = g_signal_new ("server-found",
+                                        G_TYPE_FROM_CLASS (class),
+                                        G_SIGNAL_RUN_LAST,
+                                        0,
+                                        NULL,
+                                        NULL,
+                                        g_cclosure_marshal_VOID__OBJECT,
+                                        G_TYPE_NONE,
+                                        1,
+                                        DLEYNA_SERVER_TYPE_MEDIA_DEVICE);
+
+  signals[SERVER_LOST] = g_signal_new ("server-lost",
+                                       G_TYPE_FROM_CLASS (class),
+                                       G_SIGNAL_RUN_LAST,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       g_cclosure_marshal_VOID__OBJECT,
+                                       G_TYPE_NONE,
+                                       1,
+                                       DLEYNA_SERVER_TYPE_MEDIA_DEVICE);
+}
+
+GoaDlnaServerManager *
+goa_dlna_server_manager_dup_singleton (void)
+{
+  return g_object_new (GOA_TYPE_DLNA_SERVER_MANAGER, NULL);
+}
+
+GList *
+goa_dlna_server_manager_dup_servers (GoaDlnaServerManager *self)
+{
+  GoaDlnaServerManagerPrivate *priv = self->priv;
+  GList *servers;
+
+  servers = g_hash_table_get_values (priv->servers);
+  g_list_foreach (servers, (GFunc) g_object_ref, NULL);
+
+  return servers;
+}
diff --git a/src/goabackend/goadlnaservermanager.h b/src/goabackend/goadlnaservermanager.h
new file mode 100644
index 0000000..693b410
--- /dev/null
+++ b/src/goabackend/goadlnaservermanager.h
@@ -0,0 +1,71 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2014 Pranav Kant
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. *
+ */
+
+#ifndef GOA_DLNA_SERVER_MANAGER_H
+#define GOA_DLNA_SERVER_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GOA_TYPE_DLNA_SERVER_MANAGER (goa_dlna_server_manager_get_type ())
+
+#define GOA_DLNA_SERVER_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GOA_TYPE_DLNA_SERVER_MANAGER, GoaDlnaServerManager))
+
+#define GOA_DLNA_SERVER_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GOA_TYPE_DLNA_SERVER_MANAGER, GoaDlnaServerManagerClass))
+
+#define GOA_IS_DLNA_SERVER_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GOA_TYPE_DLNA_SERVER_MANAGER))
+
+#define GOA_IS_DLNA_SERVER_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GOA_TYPE_DLNA_SERVER_MANAGER))
+
+#define GOA_DLNA_SERVER_MANAGER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GOA_TYPE_DLNA_SERVER_MANAGER, GoaDlnaServerManagerClass))
+
+typedef struct _GoaDlnaServerManager        GoaDlnaServerManager;
+typedef struct _GoaDlnaServerManagerClass   GoaDlnaServerManagerClass;
+typedef struct _GoaDlnaServerManagerPrivate GoaDlnaServerManagerPrivate;
+
+struct _GoaDlnaServerManager
+{
+  GObject parent_instance;
+  GoaDlnaServerManagerPrivate *priv;
+};
+
+struct _GoaDlnaServerManagerClass
+{
+  GObjectClass parent_class;
+};
+
+GType                       goa_dlna_server_manager_get_type      (void) G_GNUC_CONST;
+
+GoaDlnaServerManager       *goa_dlna_server_manager_dup_singleton (void);
+
+GList                      *goa_dlna_server_manager_dup_servers   (GoaDlnaServerManager *self);
+
+G_END_DECLS
+
+#endif /* GOA_DLNA_SERVER_MANAGER_H */
diff --git a/src/goabackend/goamediaserverprovider.c b/src/goabackend/goamediaserverprovider.c
new file mode 100644
index 0000000..2dc8fd6
--- /dev/null
+++ b/src/goabackend/goamediaserverprovider.c
@@ -0,0 +1,624 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2014 Pranav Kant
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "goaprovider.h"
+#include "goautils.h"
+#include "goaprovider-priv.h"
+#include "goamediaserverprovider.h"
+#include "goadleynaservermanager.h"
+#include "goadleynaservermediadevice.h"
+#include "goadlnaservermanager.h"
+
+/**
+ * GoaMediaServerProvider:
+ *
+ * The #GoaMediaServerProvider structure contains only private data and should
+ * only be accessed using the provided API.
+ */
+struct _GoaMediaServerProvider
+{
+  GoaProvider parent_instance;
+  GoaDlnaServerManager *dlna_mngr;
+};
+
+typedef struct _GoaMediaServerProviderClass GoaMediaServerProviderClass;
+
+struct _GoaMediaServerProviderClass
+{
+  GoaProviderClass parent_class;
+};
+
+/**
+ * SECTION:goamediaserverprovider
+ * @title: GoaMediaServerProvider
+ * @short_description: A provider for Media Server
+ *
+ * #GoaMediaServerProvider is used for handling Media Servers.
+ */
+
+G_DEFINE_TYPE_WITH_CODE (GoaMediaServerProvider, goa_media_server_provider, GOA_TYPE_PROVIDER,
+                         goa_provider_ensure_extension_points_registered ();
+                         g_io_extension_point_implement (GOA_PROVIDER_EXTENSION_POINT_NAME,
+                                                         g_define_type_id,
+                                                         GOA_MEDIA_SERVER_NAME,
+                                                         0));
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static const gchar *
+get_provider_type (GoaProvider *provider)
+{
+  return GOA_MEDIA_SERVER_NAME;
+}
+
+static gchar *
+get_provider_name (GoaProvider *provider,
+                   GoaObject   *object)
+{
+  return g_strdup (_("Media Server"));
+}
+
+static GoaProviderGroup
+get_provider_group (GoaProvider *provider)
+{
+  return GOA_PROVIDER_GROUP_BRANDED;
+}
+
+static GoaProviderFeatures
+get_provider_features (GoaProvider *provider)
+{
+  return GOA_PROVIDER_FEATURE_BRANDED |
+         GOA_PROVIDER_FEATURE_PHOTOS;
+}
+
+static GIcon *
+get_provider_icon (GoaProvider *provider, GoaObject *object)
+{
+  return g_themed_icon_new_with_default_fallbacks ("network-server-symbolic");
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+build_object (GoaProvider        *provider,
+              GoaObjectSkeleton  *object,
+              GKeyFile           *key_file,
+              const gchar        *group,
+              GDBusConnection    *connection,
+              gboolean            just_added,
+              GError            **error)
+{
+  gboolean ret;
+  GoaAccount *account;
+  GoaMediaServer *mediaserver;
+  GoaPhotos *photos;
+  const gchar *udn;
+  gboolean photos_enabled;
+
+  mediaserver = NULL;
+  photos = NULL;
+
+  ret = FALSE;
+
+  /* Chain up */
+  if (!GOA_PROVIDER_CLASS (goa_media_server_provider_parent_class)->build_object (provider,
+                                                                                  object,
+                                                                                  key_file,
+                                                                                  group,
+                                                                                  connection,
+                                                                                  just_added,
+                                                                                  error))
+    goto out;
+
+  account = goa_object_get_account (GOA_OBJECT (object));
+  udn = goa_account_get_identity (account);
+
+  /* Photos */
+  photos = goa_object_get_photos (GOA_OBJECT (object));
+  photos_enabled = g_key_file_get_boolean (key_file, group, "PhotosEnabled", NULL);
+  if (photos_enabled)
+    {
+      if (photos == NULL)
+        {
+          photos = goa_photos_skeleton_new ();
+          goa_object_skeleton_set_photos (object, photos);
+        }
+    }
+  else
+    {
+      if (photos == NULL)
+        goa_object_skeleton_set_photos (object, NULL);
+    }
+
+  /* Media Server */
+  mediaserver = goa_object_get_media_server (GOA_OBJECT (object));
+  if (mediaserver == NULL)
+    {
+      mediaserver = goa_media_server_skeleton_new ();
+      g_object_set (G_OBJECT (mediaserver),
+                    "dlna-supported", TRUE,
+                    "udn", udn,
+                    NULL);
+      goa_object_skeleton_set_media_server (object, mediaserver);
+    }
+
+  if (just_added)
+    {
+      goa_account_set_photos_disabled (account, !photos_enabled);
+
+      g_signal_connect (account,
+                        "notify::photos-disabled",
+                        G_CALLBACK (goa_util_account_notify_property_cb),
+                        "PhotosEnabled");
+    }
+
+  ret = TRUE;
+
+out:
+  g_clear_object (&mediaserver);
+  g_clear_object (&photos);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+ensure_credentials_sync (GoaProvider         *provider,
+                         GoaObject           *object,
+                         gint                *out_expires_in,
+                         GCancellable        *cancellable,
+                         GError             **error)
+{
+  GVariant *credentials;
+  gboolean ret;
+
+  credentials = NULL;
+  ret = FALSE;
+
+  credentials = goa_utils_lookup_credentials_sync (provider,
+                                                   object,
+                                                   cancellable,
+                                                   error);
+
+  if (credentials == NULL)
+    {
+      if (error != NULL)
+        {
+          (*error)->domain = GOA_ERROR;
+          (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
+          goto out;
+        }
+    }
+
+  if (out_expires_in != NULL)
+    *out_expires_in = 0;
+
+  ret = TRUE;
+
+ out:
+  if (credentials != NULL)
+    g_variant_unref (credentials);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+add_list_box_row (GtkWidget *list_box,
+                  DleynaServerMediaDevice *server)
+{
+  GtkWidget *label;
+  GtkWidget *row;
+  const gchar *name;
+
+  row = gtk_list_box_row_new ();
+  g_object_set_data_full (G_OBJECT (row), "server", g_object_ref (server), g_object_unref);
+  gtk_container_add (GTK_CONTAINER (list_box), row);
+
+  name = dleyna_server_media_device_get_friendly_name (server);
+  label = gtk_label_new (name);
+  gtk_widget_set_margin_start (label, 20);
+  gtk_widget_set_margin_end (label, 20);
+  gtk_widget_set_margin_top (label, 12);
+  gtk_widget_set_margin_bottom (label, 12);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_container_add (GTK_CONTAINER (row), label);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  GtkDialog *dialog;
+  GMainLoop *loop;
+  GoaDlnaServerManager *dlna_mngr;
+
+  gchar *friendly_name;
+  gchar *udn;
+
+  gchar *account_object_path;
+
+  GError *error;
+} AddAccountData;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+server_found_cb (GoaDlnaServerManager *dlna_mngr,
+                 DleynaServerMediaDevice *server,
+                 GtkWidget *list_box)
+{
+  add_list_box_row (list_box, server);
+  gtk_widget_show_all (list_box);
+}
+
+static void
+server_lost_cb (GoaDlnaServerManager *dlna_mngr,
+                DleynaServerMediaDevice *server,
+                GtkWidget *list_box)
+{
+  GList *children;
+  GList *l;
+  const gchar *udn;
+
+  children = gtk_container_get_children (GTK_CONTAINER (list_box));
+  udn = dleyna_server_media_device_get_udn (server);
+
+  for (l = children; l != NULL; l = l->next)
+    {
+      DleynaServerMediaDevice *tmp_server;
+      GtkWidget *row = GTK_WIDGET (l->data);
+      const gchar *tmp_udn;
+
+      tmp_server = DLEYNA_SERVER_MEDIA_DEVICE (g_object_get_data (G_OBJECT (row), "server"));
+      tmp_udn = dleyna_server_media_device_get_udn (tmp_server);
+      if (g_strcmp0 (tmp_udn, udn) == 0)
+        {
+          gtk_container_remove (GTK_CONTAINER (list_box), row);
+          break;
+        }
+    }
+
+  g_list_free (children);
+}
+
+static void
+list_box_activate_cb (GtkListBox *list_box,
+                      GtkListBoxRow *row,
+                      gpointer user_data)
+{
+  AddAccountData *data = user_data;
+  DleynaServerMediaDevice *device;
+  const gchar *friendly_name;
+  const gchar *udn;
+
+  device = DLEYNA_SERVER_MEDIA_DEVICE (g_object_get_data (G_OBJECT (row), "server"));
+  friendly_name = dleyna_server_media_device_get_friendly_name (device);
+  udn = dleyna_server_media_device_get_udn (device);
+
+  data->udn = g_strdup (udn);
+  data->friendly_name = g_strdup (friendly_name);
+  gtk_dialog_response (data->dialog, GTK_RESPONSE_OK);
+}
+
+static void
+update_header_func (GtkListBoxRow *row,
+                    GtkListBoxRow *before,
+                    gpointer user_data)
+{
+  GtkWidget *current;
+
+  if (before == NULL)
+    return;
+
+  current = gtk_list_box_row_get_header (row);
+  if (current == NULL)
+    {
+      current = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+      gtk_widget_show (current);
+      gtk_list_box_row_set_header (row, current);
+    }
+}
+
+static void
+create_account_details_ui (GoaProvider    *provider,
+                           GtkDialog      *dialog,
+                           GtkBox         *vbox,
+                           AddAccountData *data)
+{
+  GList *l;
+  GList *servers;
+  GtkStyleContext *context;
+  GtkWidget *label;
+  GtkWidget *list_box;
+  GtkWidget *grid0;
+  GtkWidget *grid1;
+  GtkWidget *scrolled_window;
+  gchar *markup;
+  gint height;
+
+  goa_utils_set_dialog_title (provider, dialog, TRUE);
+
+  grid0 = gtk_grid_new ();
+  gtk_container_set_border_width (GTK_CONTAINER (grid0), 5);
+  gtk_widget_set_margin_bottom (grid0, 6);
+  gtk_widget_set_margin_start (grid0, 36);
+  gtk_widget_set_margin_end (grid0, 36);
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (grid0), GTK_ORIENTATION_VERTICAL);
+  gtk_grid_set_row_spacing (GTK_GRID (grid0), 12);
+  gtk_container_add (GTK_CONTAINER (vbox), grid0);
+
+  label = gtk_label_new (_("Personal content can be added to your applications through a media server 
account."));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_label_set_max_width_chars (GTK_LABEL (label), 40);
+  gtk_container_add (GTK_CONTAINER (grid0), label);
+
+  grid1 = gtk_grid_new ();
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (grid1), GTK_ORIENTATION_VERTICAL);
+  gtk_grid_set_row_spacing (GTK_GRID (grid1), 6);
+  gtk_container_add (GTK_CONTAINER (grid0), grid1);
+
+  label = gtk_label_new ("");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  markup = g_strdup_printf ("<b>%s</b>", _("Available Media Servers"));
+  gtk_label_set_markup (GTK_LABEL (label), markup);
+  g_free (markup);
+  gtk_container_add (GTK_CONTAINER (grid1), label);
+
+  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_hexpand (scrolled_window, TRUE);
+  gtk_widget_set_vexpand (scrolled_window, TRUE);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                  GTK_POLICY_AUTOMATIC,
+                                  GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
+  gtk_container_add (GTK_CONTAINER (grid1), scrolled_window);
+
+  list_box = gtk_list_box_new ();
+  gtk_list_box_set_header_func (GTK_LIST_BOX (list_box), update_header_func, NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_window), list_box);
+  g_signal_connect (list_box, "row-activated", G_CALLBACK (list_box_activate_cb), data);
+  g_signal_connect_object (data->dlna_mngr, "server-found", G_CALLBACK (server_found_cb), list_box, 0);
+  g_signal_connect_object (data->dlna_mngr, "server-lost", G_CALLBACK (server_lost_cb), list_box, 0);
+
+  servers = goa_dlna_server_manager_dup_servers (data->dlna_mngr);
+  for (l = servers; l != NULL; l = l->next)
+    {
+      DleynaServerMediaDevice *server = DLEYNA_SERVER_MEDIA_DEVICE (l->data);
+      add_list_box_row (list_box, server);
+    }
+
+  g_list_free_full (servers, g_object_unref);
+
+  label = gtk_label_new (_("No media servers found"));
+  context = gtk_widget_get_style_context (label);
+  gtk_style_context_add_class (context, "dim-label");
+  gtk_list_box_set_placeholder (GTK_LIST_BOX (list_box), label);
+  gtk_widget_show (label);
+
+  gtk_window_get_size (GTK_WINDOW (data->dialog), NULL, &height);
+  gtk_widget_set_size_request (GTK_WIDGET (data->dialog), -1, height);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+add_account_cb (GoaManager *manager, GAsyncResult *res, gpointer user_data)
+{
+  AddAccountData *data = user_data;
+  goa_manager_call_add_account_finish (manager,
+                                       &data->account_object_path,
+                                       res,
+                                       &data->error);
+  g_main_loop_quit (data->loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GoaObject *
+add_account (GoaProvider  *provider,
+             GoaClient    *client,
+             GtkDialog    *dialog,
+             GtkBox       *vbox,
+             GError      **error)
+{
+  GoaMediaServerProvider *self = GOA_MEDIA_SERVER_PROVIDER (provider);
+  AddAccountData data;
+  GVariantBuilder details;
+  GVariantBuilder credentials;
+  GoaObject *ret;
+  const gchar *provider_type;
+  gint response;
+
+  ret = NULL;
+
+  memset (&data, 0, sizeof (AddAccountData));
+  data.loop = g_main_loop_new (NULL, FALSE);
+  data.dialog = dialog;
+  data.error = NULL;
+
+  if (self->dlna_mngr == NULL)
+    self->dlna_mngr = goa_dlna_server_manager_dup_singleton ();
+  data.dlna_mngr = self->dlna_mngr;
+
+  create_account_details_ui (provider, dialog, vbox, &data);
+  gtk_widget_show_all (GTK_WIDGET (vbox));
+
+  response = gtk_dialog_run (dialog);
+  if (response != GTK_RESPONSE_OK)
+    {
+      g_set_error (&data.error,
+                   GOA_ERROR,
+                   GOA_ERROR_DIALOG_DISMISSED,
+                   _("Dialog was dismissed"));
+      goto out;
+    }
+
+  /* See if there's already an account of this type with the
+   * given identity.
+   */
+  provider_type = goa_provider_get_provider_type (provider);
+  if (!goa_utils_check_duplicate (client,
+                                  data.udn,
+                                  data.friendly_name,
+                                  provider_type,
+                                  (GoaPeekInterfaceFunc) goa_object_peek_account,
+                                  &data.error))
+    goto out;
+
+  gtk_widget_hide (GTK_WIDGET (dialog));
+
+  /* No authentication required, so passing an empty variant. */
+  g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
+
+  g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
+  g_variant_builder_add (&details, "{ss}", "PhotosEnabled", "true");
+
+  /* OK, everything is dandy, add the account */
+  /* we want the GoaClient to update before this method returns (so it
+   * can create a proxy for the new object) so run the mainloop while
+   * waiting for this to complete
+   */
+  goa_manager_call_add_account (goa_client_get_manager (client),
+                                goa_provider_get_provider_type (provider),
+                                data.udn,
+                                data.friendly_name,
+                                g_variant_builder_end (&credentials),
+                                g_variant_builder_end (&details),
+                                NULL,
+                                (GAsyncReadyCallback) add_account_cb,
+                                &data);
+  g_main_loop_run (data.loop);
+  if (data.error != NULL)
+    goto out;
+
+  ret = GOA_OBJECT (g_dbus_object_manager_get_object (goa_client_get_object_manager (client),
+                                                      data.account_object_path));
+
+ out:
+  /* We might have an object even when data.error is set.
+   * eg., if we failed to store the credentials in the keyring.
+  */
+  if (data.error != NULL)
+    g_propagate_error (error, data.error);
+  else
+    g_assert (ret != NULL);
+
+  g_free (data.account_object_path);
+  g_free (data.friendly_name);
+  g_free (data.udn);
+  if (data.loop != NULL)
+    g_main_loop_unref (data.loop);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+refresh_account (GoaProvider  *provider,
+                 GoaClient    *client,
+                 GoaObject    *object,
+                 GtkWindow    *parent,
+                 GError      **error)
+{
+  GoaAccount *account;
+  GVariantBuilder credentials;
+  gboolean ret;
+
+  ret = FALSE;
+
+  g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
+
+  if (!goa_utils_store_credentials_for_object_sync (provider,
+                                                    object,
+                                                    g_variant_builder_end (&credentials),
+                                                    NULL, /* GCancellable */
+                                                    error))
+    goto out;
+
+  account = goa_object_peek_account (object);
+  goa_account_call_ensure_credentials (account,
+                                       NULL, /* GCancellable */
+                                       NULL, NULL); /* callback, user_data */
+  ret = TRUE;
+
+ out:
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+show_account (GoaProvider         *provider,
+              GoaClient           *client,
+              GoaObject           *object,
+              GtkBox              *vbox,
+              GtkGrid             *grid,
+              GtkGrid             *right)
+{
+  gint row = 0;
+
+  goa_util_add_account_info (grid, row++, object);
+
+  goa_util_add_row_switch_from_keyfile_with_blurb (grid, row++, object,
+                                                   _("Use for"),
+                                                   "photos-disabled",
+                                                   _("_Photos"));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+goa_media_server_provider_dispose (GObject *object)
+{
+  GoaMediaServerProvider *self = GOA_MEDIA_SERVER_PROVIDER (object);
+
+  g_clear_object (&self->dlna_mngr);
+
+  G_OBJECT_CLASS (goa_media_server_provider_parent_class)->dispose (object);
+}
+
+static void
+goa_media_server_provider_init (GoaMediaServerProvider *self)
+{
+}
+
+static void
+goa_media_server_provider_class_init (GoaMediaServerProviderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GoaProviderClass *provider_class = GOA_PROVIDER_CLASS (klass);
+
+  object_class->dispose = goa_media_server_provider_dispose;
+
+  provider_class->get_provider_type       = get_provider_type;
+  provider_class->get_provider_name       = get_provider_name;
+  provider_class->get_provider_group      = get_provider_group;
+  provider_class->get_provider_features   = get_provider_features;
+  provider_class->get_provider_icon       = get_provider_icon;
+  provider_class->add_account             = add_account;
+  provider_class->refresh_account         = refresh_account;
+  provider_class->build_object            = build_object;
+  provider_class->show_account            = show_account;
+  provider_class->ensure_credentials_sync = ensure_credentials_sync;
+}
diff --git a/src/goabackend/goamediaserverprovider.h b/src/goabackend/goamediaserverprovider.h
new file mode 100644
index 0000000..3e5b66b
--- /dev/null
+++ b/src/goabackend/goamediaserverprovider.h
@@ -0,0 +1,40 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2014 Pranav Kant
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GOA_BACKEND_INSIDE_GOA_BACKEND_H__) && !defined (GOA_BACKEND_COMPILATION)
+#error "Only <goabackend/goabackend.h> can be included directly."
+#endif
+
+#ifndef __GOA_MEDIA_SERVER_PROVIDER_H__
+#define __GOA_MEDIA_SERVER_PROVIDER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GOA_TYPE_MEDIA_SERVER_PROVIDER   (goa_media_server_provider_get_type ())
+#define GOA_MEDIA_SERVER_PROVIDER(o)     (G_TYPE_CHECK_INSTANCE_CAST ((o), GOA_TYPE_MEDIA_SERVER_PROVIDER, 
GoaMediaServerProvider))
+#define GOA_IS_MEDIA_SERVER_PROVIDER(o)  (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOA_TYPE_MEDIA_SERVER_PROVIDER))
+
+typedef struct _GoaMediaServerProvider GoaMediaServerProvider;
+
+GType goa_media_server_provider_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GOA_MEDIA_SERVER_PROVIDER_H__ */
diff --git a/src/goabackend/goaprovider.c b/src/goabackend/goaprovider.c
index f163597..95c0195 100644
--- a/src/goabackend/goaprovider.c
+++ b/src/goabackend/goaprovider.c
@@ -33,6 +33,7 @@
 #include "goawindowsliveprovider.h"
 #include "goatelepathyfactory.h"
 #include "goapocketprovider.h"
+#include "goamediaserverprovider.h"
 
 #ifdef GOA_KERBEROS_ENABLED
 #include "goakerberosprovider.h"
@@ -789,6 +790,9 @@ static struct
 #ifdef GOA_KERBEROS_ENABLED
   { GOA_KERBEROS_NAME, goa_kerberos_provider_get_type },
 #endif
+#ifdef GOA_MEDIA_SERVER_ENABLED
+  { GOA_MEDIA_SERVER_NAME, goa_media_server_provider_get_type },
+#endif
 #ifdef GOA_YAHOO_ENABLED
   { GOA_YAHOO_NAME, goa_yahoo_provider_get_type },
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]