Blame src/gom-dlna-server.c

Packit f01ec2
/*
Packit f01ec2
 * GNOME Online Miners - crawls through your online content
Packit f01ec2
 * Copyright (c) 2014, 2015 Pranav Kant
Packit f01ec2
 *
Packit f01ec2
 * This program is free software; you can redistribute it and/or
Packit f01ec2
 * modify it under the terms of the GNU General Public License
Packit f01ec2
 * as published by the Free Software Foundation; either version 2
Packit f01ec2
 * of the License, or (at your option) any later version.
Packit f01ec2
 *
Packit f01ec2
 * This program is distributed in the hope that it will be useful,
Packit f01ec2
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit f01ec2
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit f01ec2
 * GNU General Public License for more details.
Packit f01ec2
 *
Packit f01ec2
 * You should have received a copy of the GNU General Public License
Packit f01ec2
 * along with this program; if not, write to the Free Software
Packit f01ec2
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit f01ec2
 * 02110-1301, USA.
Packit f01ec2
 *
Packit f01ec2
 * Author: Pranav Kant <pranavk@gnome.org>
Packit f01ec2
 *
Packit f01ec2
 */
Packit f01ec2
Packit f01ec2
#include "config.h"
Packit f01ec2
Packit f01ec2
#include "gom-dleyna-server-media-device.h"
Packit f01ec2
#include "gom-upnp-media-container2.h"
Packit f01ec2
#include "gom-dlna-server.h"
Packit f01ec2
#include "gom-utils.h"
Packit f01ec2
Packit f01ec2
struct _GomDlnaServerPrivate
Packit f01ec2
{
Packit f01ec2
  DleynaServerMediaDevice *device;
Packit f01ec2
  UpnpMediaContainer2 *container;
Packit f01ec2
  GBusType bus_type;
Packit f01ec2
  GDBusProxyFlags flags;
Packit f01ec2
  gchar *object_path;
Packit f01ec2
  gchar *well_known_name;
Packit f01ec2
};
Packit f01ec2
Packit f01ec2
Packit f01ec2
enum{
Packit f01ec2
  PROP_0,
Packit f01ec2
  PROP_BUS_TYPE,
Packit f01ec2
  PROP_FLAGS,
Packit f01ec2
  PROP_OBJECT_PATH,
Packit f01ec2
  PROP_WELL_KNOWN_NAME,
Packit f01ec2
};
Packit f01ec2
Packit f01ec2
static void gom_dlna_server_initable_iface_init (GInitableIface *iface);
Packit f01ec2
Packit f01ec2
G_DEFINE_TYPE_WITH_CODE (GomDlnaServer, gom_dlna_server, G_TYPE_OBJECT,
Packit f01ec2
                         G_ADD_PRIVATE (GomDlnaServer)
Packit f01ec2
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
Packit f01ec2
                                                gom_dlna_server_initable_iface_init));
Packit f01ec2
Packit f01ec2
Packit f01ec2
static GomDlnaPhotoItem *
Packit f01ec2
photo_item_new (GVariant *var)
Packit f01ec2
{
Packit f01ec2
  GVariant *tmp;
Packit f01ec2
  GomDlnaPhotoItem *photo;
Packit f01ec2
  const gchar *str;
Packit f01ec2
Packit f01ec2
  photo = g_slice_new0 (GomDlnaPhotoItem);
Packit f01ec2
Packit f01ec2
  g_variant_lookup (var, "DisplayName", "&s", &str);
Packit f01ec2
  photo->name = gom_filename_strip_extension (str);
Packit f01ec2
Packit f01ec2
  g_variant_lookup (var, "MIMEType", "&s", &str);
Packit f01ec2
  photo->mimetype = g_strdup (str);
Packit f01ec2
Packit f01ec2
  g_variant_lookup (var, "Path", "&o", &str);
Packit f01ec2
  photo->path = g_strdup (str);
Packit f01ec2
Packit f01ec2
  g_variant_lookup (var, "Type", "s", &str);
Packit f01ec2
  photo->type = g_strdup (str);
Packit f01ec2
Packit f01ec2
  if (g_str_equal (photo->type, "container"))
Packit f01ec2
    {
Packit f01ec2
      photo->url = NULL;
Packit f01ec2
      goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  g_variant_lookup (var, "URLs", "@as", &tmp);
Packit f01ec2
  g_variant_get_child (tmp, 0, "&s", &str);
Packit f01ec2
  photo->url = g_strdup (str);
Packit f01ec2
  g_variant_unref (tmp);
Packit f01ec2
Packit f01ec2
 out:
Packit f01ec2
  return photo;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static GList *
Packit f01ec2
process_children (GVariant *children, GList **photos_list)
Packit f01ec2
{
Packit f01ec2
  GVariantIter *iter = NULL;
Packit f01ec2
  GVariant *var = NULL;
Packit f01ec2
  GList *containers = NULL;
Packit f01ec2
  GomDlnaPhotoItem *photo;
Packit f01ec2
Packit f01ec2
  g_variant_get (children, "aa{sv}", &iter);
Packit f01ec2
  while (g_variant_iter_loop (iter, "@a{sv}", &var))
Packit f01ec2
    {
Packit f01ec2
      photo = photo_item_new (var);
Packit f01ec2
      if (g_str_equal (photo->type, "image.photo"))
Packit f01ec2
        {
Packit f01ec2
          *photos_list = g_list_prepend (*photos_list, photo);
Packit f01ec2
        }
Packit f01ec2
      else if (g_str_equal (photo->type, "container"))
Packit f01ec2
        {
Packit f01ec2
          containers = g_list_prepend (containers, g_strdup (photo->path));
Packit f01ec2
          gom_dlna_photo_item_free (photo);
Packit f01ec2
        }
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  return containers;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
find_photos (const gchar   *obj_path,
Packit f01ec2
             GList        **photos_list)
Packit f01ec2
{
Packit f01ec2
  GError *error = NULL;
Packit f01ec2
  GList *containers = NULL;
Packit f01ec2
  GList *l;
Packit f01ec2
  GVariant *children = NULL;
Packit f01ec2
  UpnpMediaContainer2 *proxy = NULL;
Packit f01ec2
  const gchar *const filter[] = {"DisplayName","Type","Path", "URLs", "MIMEType", NULL};
Packit f01ec2
Packit f01ec2
  proxy = upnp_media_container2_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
Packit f01ec2
                                                        G_DBUS_PROXY_FLAGS_NONE,
Packit f01ec2
                                                        "com.intel.dleyna-server",
Packit f01ec2
                                                        obj_path,
Packit f01ec2
                                                        NULL, /* GCancellable */
Packit f01ec2
                                                        &error);
Packit f01ec2
Packit f01ec2
  if (error != NULL)
Packit f01ec2
    {
Packit f01ec2
      g_warning ("Unable to get proxy for Upnp.MediaContainer2 : %s",
Packit f01ec2
                 error->message);
Packit f01ec2
      g_error_free (error);
Packit f01ec2
      goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  upnp_media_container2_call_list_children_sync (proxy,
Packit f01ec2
                                                 0,
Packit f01ec2
                                                 0,
Packit f01ec2
                                                 filter,
Packit f01ec2
                                                 &children,
Packit f01ec2
                                                 NULL, /* GCancellable */
Packit f01ec2
                                                 &error);
Packit f01ec2
Packit f01ec2
  if (error != NULL)
Packit f01ec2
    {
Packit f01ec2
      g_warning ("Unable to call ListChildren : %s",
Packit f01ec2
                 error->message);
Packit f01ec2
      g_error_free (error);
Packit f01ec2
      goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  if (children == NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  containers = process_children (children, photos_list);
Packit f01ec2
  if (containers == NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  for (l = containers; l != NULL; l = l->next)
Packit f01ec2
    {
Packit f01ec2
      const gchar *obj_path = (gchar *) l->data;
Packit f01ec2
      find_photos (obj_path, photos_list);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
 out:
Packit f01ec2
  g_list_free_full (containers, g_free);
Packit f01ec2
  g_clear_pointer (&children, (GDestroyNotify) g_variant_unref);
Packit f01ec2
  g_clear_object (&proxy);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_dispose (GObject *object)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServer *self = GOM_DLNA_SERVER (object);
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
Packit f01ec2
  g_clear_object (&priv->device);
Packit f01ec2
  g_clear_object (&priv->container);
Packit f01ec2
Packit f01ec2
  G_OBJECT_CLASS (gom_dlna_server_parent_class)->dispose (object);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_finalize (GObject *object)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServer *self = GOM_DLNA_SERVER (object);
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
Packit f01ec2
  g_free (priv->well_known_name);
Packit f01ec2
  g_free (priv->object_path);
Packit f01ec2
Packit f01ec2
  G_OBJECT_CLASS (gom_dlna_server_parent_class)->finalize (object);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_get_property (GObject *object,
Packit f01ec2
                              guint prop_id,
Packit f01ec2
                              GValue *value,
Packit f01ec2
                              GParamSpec *pspec)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServer *self = GOM_DLNA_SERVER (object);
Packit f01ec2
Packit f01ec2
  switch (prop_id)
Packit f01ec2
    {
Packit f01ec2
    case PROP_OBJECT_PATH:
Packit f01ec2
      g_value_set_string (value, gom_dlna_server_get_object_path (self));
Packit f01ec2
      break;
Packit f01ec2
Packit f01ec2
    default:
Packit f01ec2
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit f01ec2
      break;
Packit f01ec2
    }
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_set_property (GObject *object,
Packit f01ec2
                              guint prop_id,
Packit f01ec2
                              const GValue *value,
Packit f01ec2
                              GParamSpec *pspec)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServer *self = GOM_DLNA_SERVER (object);
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
Packit f01ec2
  switch (prop_id)
Packit f01ec2
    {
Packit f01ec2
    case PROP_BUS_TYPE:
Packit f01ec2
      priv->bus_type = g_value_get_enum (value);
Packit f01ec2
      break;
Packit f01ec2
Packit f01ec2
    case PROP_FLAGS:
Packit f01ec2
      priv->flags = g_value_get_flags (value);
Packit f01ec2
      break;
Packit f01ec2
Packit f01ec2
    case PROP_OBJECT_PATH:
Packit f01ec2
      priv->object_path = g_value_dup_string (value);
Packit f01ec2
      break;
Packit f01ec2
Packit f01ec2
    case PROP_WELL_KNOWN_NAME:
Packit f01ec2
      priv->well_known_name = g_value_dup_string (value);
Packit f01ec2
      break;
Packit f01ec2
Packit f01ec2
    default:
Packit f01ec2
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit f01ec2
      break;
Packit f01ec2
    }
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_init (GomDlnaServer *self)
Packit f01ec2
{
Packit f01ec2
  self->priv = gom_dlna_server_get_instance_private (self);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_class_init (GomDlnaServerClass *class)
Packit f01ec2
{
Packit f01ec2
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Packit f01ec2
Packit f01ec2
  gobject_class->dispose = gom_dlna_server_dispose;
Packit f01ec2
  gobject_class->finalize = gom_dlna_server_finalize;
Packit f01ec2
  gobject_class->set_property = gom_dlna_server_set_property;
Packit f01ec2
  gobject_class->get_property = gom_dlna_server_get_property;
Packit f01ec2
Packit f01ec2
  g_object_class_install_property (gobject_class,
Packit f01ec2
                                   PROP_BUS_TYPE,
Packit f01ec2
                                   g_param_spec_enum ("bus-type",
Packit f01ec2
                                                      "Bus Type",
Packit f01ec2
                                                      "The bus to connect to, defaults to the session one",
Packit f01ec2
                                                      G_TYPE_BUS_TYPE,
Packit f01ec2
                                                      G_BUS_TYPE_SESSION,
Packit f01ec2
                                                      G_PARAM_WRITABLE |
Packit f01ec2
                                                      G_PARAM_CONSTRUCT_ONLY |
Packit f01ec2
                                                      G_PARAM_STATIC_STRINGS));
Packit f01ec2
Packit f01ec2
  g_object_class_install_property (gobject_class,
Packit f01ec2
                                   PROP_FLAGS,
Packit f01ec2
                                   g_param_spec_flags ("flags",
Packit f01ec2
                                                       "Flags",
Packit f01ec2
                                                       "Proxy flags",
Packit f01ec2
                                                       G_TYPE_DBUS_PROXY_FLAGS,
Packit f01ec2
                                                       G_DBUS_PROXY_FLAGS_NONE,
Packit f01ec2
                                                       G_PARAM_READWRITE |
Packit f01ec2
                                                       G_PARAM_CONSTRUCT_ONLY |
Packit f01ec2
                                                       G_PARAM_STATIC_STRINGS));
Packit f01ec2
Packit f01ec2
  g_object_class_install_property (gobject_class,
Packit f01ec2
                                   PROP_OBJECT_PATH,
Packit f01ec2
                                   g_param_spec_string ("object-path",
Packit f01ec2
                                                        "Object Path",
Packit f01ec2
                                                        "The object path the proxy is for",
Packit f01ec2
                                                        NULL,
Packit f01ec2
                                                        G_PARAM_READWRITE |
Packit f01ec2
                                                        G_PARAM_CONSTRUCT_ONLY |
Packit f01ec2
                                                        G_PARAM_STATIC_STRINGS));
Packit f01ec2
Packit f01ec2
Packit f01ec2
  g_object_class_install_property (gobject_class,
Packit f01ec2
                                   PROP_WELL_KNOWN_NAME,
Packit f01ec2
                                   g_param_spec_string ("well-known-name",
Packit f01ec2
                                                        "Well-Known Name",
Packit f01ec2
                                                        "The well-known name of the service",
Packit f01ec2
                                                        NULL,
Packit f01ec2
                                                        G_PARAM_READWRITE |
Packit f01ec2
                                                        G_PARAM_CONSTRUCT_ONLY |
Packit f01ec2
                                                        G_PARAM_STATIC_STRINGS));
Packit f01ec2
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
void
Packit f01ec2
gom_dlna_photo_item_free (GomDlnaPhotoItem *photo)
Packit f01ec2
{
Packit f01ec2
  g_free (photo->name);
Packit f01ec2
  g_free (photo->mimetype);
Packit f01ec2
  g_free (photo->path);
Packit f01ec2
  g_free (photo->url);
Packit f01ec2
  g_free (photo->type);
Packit f01ec2
  g_slice_free (GomDlnaPhotoItem, photo);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
GomDlnaServer *
Packit f01ec2
gom_dlna_server_new_for_bus (GBusType bus_type,
Packit f01ec2
                             GDBusProxyFlags flags,
Packit f01ec2
                             const gchar *well_known_name,
Packit f01ec2
                             const gchar *object_path,
Packit f01ec2
                             GCancellable *cancellable,
Packit f01ec2
                             GError **error)
Packit f01ec2
{
Packit f01ec2
  return g_initable_new (GOM_TYPE_DLNA_SERVER,
Packit f01ec2
                         cancellable,
Packit f01ec2
                         error,
Packit f01ec2
                         "bus-type", bus_type,
Packit f01ec2
                         "flags", flags,
Packit f01ec2
                         "object-path", object_path,
Packit f01ec2
                         "well-known-name", well_known_name,
Packit f01ec2
                         NULL);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static gboolean
Packit f01ec2
gom_dlna_server_initable_init (GInitable *initable,
Packit f01ec2
                               GCancellable *cancellable,
Packit f01ec2
                               GError **error)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServer *self = GOM_DLNA_SERVER (initable);
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
  gboolean ret_val = TRUE;
Packit f01ec2
Packit f01ec2
  priv->device =
Packit f01ec2
    dleyna_server_media_device_proxy_new_for_bus_sync (priv->bus_type,
Packit f01ec2
                                                       G_DBUS_PROXY_FLAGS_NONE,
Packit f01ec2
                                                       priv->well_known_name,
Packit f01ec2
                                                       priv->object_path,
Packit f01ec2
                                                       NULL,
Packit f01ec2
                                                       error);
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    {
Packit f01ec2
      ret_val = FALSE;
Packit f01ec2
      goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  priv->container =
Packit f01ec2
    upnp_media_container2_proxy_new_for_bus_sync (priv->bus_type,
Packit f01ec2
                                                  G_DBUS_PROXY_FLAGS_NONE,
Packit f01ec2
                                                  priv->well_known_name,
Packit f01ec2
                                                  priv->object_path,
Packit f01ec2
                                                  NULL,
Packit f01ec2
                                                  error);
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    {
Packit f01ec2
      ret_val = FALSE;
Packit f01ec2
      goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
 out:
Packit f01ec2
  return ret_val;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_dlna_server_initable_iface_init (GInitableIface *iface)
Packit f01ec2
{
Packit f01ec2
  iface->init = gom_dlna_server_initable_init;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
const gchar *
Packit f01ec2
gom_dlna_server_get_object_path (GomDlnaServer *self)
Packit f01ec2
{
Packit f01ec2
  return self->priv->object_path;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
const gchar *
Packit f01ec2
gom_dlna_server_get_friendly_name (GomDlnaServer *self)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
Packit f01ec2
  return dleyna_server_media_device_get_friendly_name (priv->device);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
GVariant *
Packit f01ec2
gom_dlna_server_search_objects (GomDlnaServer *self, GError **error)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
  GVariant *out = NULL;
Packit f01ec2
  gchar *query = g_strdup_printf ("Type = \"image.photo\"");
Packit f01ec2
  const gchar const *filter[] = {"DisplayName", "URLs", "Path", "MIMEType", NULL};
Packit f01ec2
Packit f01ec2
  upnp_media_container2_call_search_objects_sync (priv->container,
Packit f01ec2
                                                  query,
Packit f01ec2
                                                  0,
Packit f01ec2
                                                  0,
Packit f01ec2
                                                  filter,
Packit f01ec2
                                                  &out,
Packit f01ec2
                                                  NULL,
Packit f01ec2
                                                  error);
Packit f01ec2
Packit f01ec2
Packit f01ec2
  g_free (query);
Packit f01ec2
  return out;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
GList *
Packit f01ec2
gom_dlna_server_get_photos (GomDlnaServer *server)
Packit f01ec2
{
Packit f01ec2
  GError *error = NULL;
Packit f01ec2
  GList *photos_list = NULL;
Packit f01ec2
  GVariant *out, *var;
Packit f01ec2
  GVariantIter *iter = NULL;
Packit f01ec2
  GomDlnaPhotoItem *photo;
Packit f01ec2
Packit f01ec2
  if (gom_dlna_server_get_searchable (server))
Packit f01ec2
    {
Packit f01ec2
      out = gom_dlna_server_search_objects (server, &error);
Packit f01ec2
      if (error != NULL)
Packit f01ec2
        {
Packit f01ec2
          g_warning ("Unable to search objects on server : %s",
Packit f01ec2
                     error->message);
Packit f01ec2
          g_error_free (error);
Packit f01ec2
          return NULL;
Packit f01ec2
        }
Packit f01ec2
Packit f01ec2
      g_variant_get (out, "aa{sv}", &iter);
Packit f01ec2
      while (g_variant_iter_loop (iter, "@a{sv}", &var))
Packit f01ec2
        {
Packit f01ec2
          photo = photo_item_new (var);
Packit f01ec2
          photos_list = g_list_prepend (photos_list, photo);
Packit f01ec2
        }
Packit f01ec2
Packit f01ec2
      g_variant_iter_free (iter);
Packit f01ec2
    }
Packit f01ec2
  else
Packit f01ec2
    {
Packit f01ec2
      const gchar *obj_path;
Packit f01ec2
Packit f01ec2
      obj_path = gom_dlna_server_get_object_path (server);
Packit f01ec2
      find_photos (obj_path, &photos_list);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  return photos_list;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
const gchar *
Packit f01ec2
gom_dlna_server_get_udn (GomDlnaServer *self)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
Packit f01ec2
  return dleyna_server_media_device_get_udn (priv->device);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
Packit f01ec2
gboolean
Packit f01ec2
gom_dlna_server_get_searchable (GomDlnaServer *self)
Packit f01ec2
{
Packit f01ec2
  GomDlnaServerPrivate *priv = self->priv;
Packit f01ec2
  return upnp_media_container2_get_searchable (priv->container);
Packit f01ec2
}