diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 20 | ||||
-rw-r--r-- | src/gupnp-media-server.c | 461 | ||||
-rw-r--r-- | src/gupnp-media-server.h | 79 | ||||
-rw-r--r-- | src/main.c | 323 |
4 files changed, 0 insertions, 883 deletions
diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 3ebd3916..00000000 --- a/src/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -if UNINSTALLED -shareddir = $(abs_top_builddir)/data -else -shareddir = $(datadir)/gupnp-media-server -endif - -AM_CFLAGS = $(LIBGUPNP_CFLAGS) $(LIBGUPNP_AV_CFLAGS) $(LIBGCONF_CFLAGS) \ - -I$(top_srcdir) -DDATA_DIR='"$(shareddir)"' - -bin_PROGRAMS = gupnp-media-server - -gupnp_media_server_SOURCES = main.c \ - gupnp-media-server.h \ - gupnp-media-server.c -gupnp_media_server_LDADD = $(LIBGUPNP_LIBS) \ - $(LIBGUPNP_AV_LIBS) \ - $(LIBGCONF_LIBS) -gupnp_media_server_LDFLAGS = -export-dynamic - -MAINTAINERCLEANFILES = Makefile.in diff --git a/src/gupnp-media-server.c b/src/gupnp-media-server.c deleted file mode 100644 index a4a037c5..00000000 --- a/src/gupnp-media-server.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (C) 2008 Zeeshan Ali <zeenix@gmail.com>. - * Copyright (C) 2007 OpenedHand Ltd. - * - * Author: Zeeshan Ali <zeenix@gmail.com> - * Jorn Baayen <jorn@openedhand.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - */ - -#include <string.h> -#include <libgupnp/gupnp.h> -#include <libgupnp-av/gupnp-av.h> - -#include "gupnp-media-server.h" - -#define HOME_DIR_ALIAS "/media" - -G_DEFINE_TYPE (GUPnPMediaServer, - gupnp_media_server, - GUPNP_TYPE_ROOT_DEVICE); - -struct _GUPnPMediaServerPrivate { - guint32 system_update_id; - - GUPnPService *content_dir; - - GUPnPDIDLLiteWriter *didl_writer; - GUPnPSearchCriteriaParser *search_parser; -}; - -/* Hard-coded items (mime, title, path) - * - * paths are relative to home directory - * */ -char *items[3][4] = { - { "4000", - "audio/mpeg", - "Maa", - "entertainment/songs/Maa.mp3" }, - { "4001", - "audio/mpeg", - "Hoo", - "entertainment/songs/Ho.mp3" }, - { NULL } -}; - -/* GObject stuff */ -static void -gupnp_media_server_dispose (GObject *object) -{ - GUPnPMediaServer *server; - GObjectClass *object_class; - - server = GUPNP_MEDIA_SERVER (object); - - /* Free GUPnP resources */ - if (server->priv->search_parser) { - g_object_unref (server->priv->search_parser); - server->priv->search_parser = NULL; - } - - if (server->priv->didl_writer) { - g_object_unref (server->priv->didl_writer); - server->priv->didl_writer = NULL; - } - if (server->priv->content_dir) { - g_object_unref (server->priv->content_dir); - server->priv->content_dir = NULL; - } - - /* Call super */ - object_class = G_OBJECT_CLASS (gupnp_media_server_parent_class); - object_class->dispose (object); -} - -static void -gupnp_media_server_init (GUPnPMediaServer *server) -{ - server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, - GUPNP_TYPE_MEDIA_SERVER, - GUPnPMediaServerPrivate); - - /* Create a new DIDL-Lite writer */ - server->priv->didl_writer = gupnp_didl_lite_writer_new (); - - /* Create a new search criteria parser */ - server->priv->search_parser = gupnp_search_criteria_parser_new (); -} - -static GObject * -gupnp_media_server_constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - GObjectClass *object_class; - GUPnPMediaServer *server; - GUPnPServiceInfo *service; - GUPnPContext *context; - - object_class = G_OBJECT_CLASS (gupnp_media_server_parent_class); - object = object_class->constructor (type, - n_construct_params, - construct_params); - - if (object == NULL) - return NULL; - - server = GUPNP_MEDIA_SERVER (object); - - /* Connect ContentDirectory signals */ - service = gupnp_device_info_get_service - (GUPNP_DEVICE_INFO (server), - "urn:schemas-upnp-org:service:ContentDirectory:2"); - if (service != NULL) { - GError *error; - - server->priv->content_dir = GUPNP_SERVICE (service); - - error = NULL; - gupnp_service_signals_autoconnect (server->priv->content_dir, - server, - &error); - if (error) { - g_warning ("Error autoconnecting signals: %s", - error->message); - g_error_free (error); - } - } - - context = gupnp_device_info_get_context (GUPNP_DEVICE_INFO (server)); - - /* Host user's home dir */ - gupnp_context_host_path (context, g_get_home_dir (), HOME_DIR_ALIAS); - - return object; -} - -static void -gupnp_media_server_class_init (GUPnPMediaServerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = gupnp_media_server_dispose; - object_class->constructor = gupnp_media_server_constructor; - - g_type_class_add_private (klass, sizeof (GUPnPMediaServerPrivate)); -} - -static void -add_root_container (GUPnPDIDLLiteWriter *didl_writer) -{ - guint child_count; - - /* Count items */ - for (child_count = 0; items[child_count][0]; child_count++); - - gupnp_didl_lite_writer_start_container (didl_writer, - "0", - "-1", - child_count, - FALSE, - FALSE); - - gupnp_didl_lite_writer_add_string - (didl_writer, - "class", - GUPNP_DIDL_LITE_WRITER_NAMESPACE_UPNP, - NULL, - "object.container.storageFolder"); - - /* End of Container */ - gupnp_didl_lite_writer_end_container (didl_writer); -} - -static void -add_item (GUPnPContext *context, - GUPnPDIDLLiteWriter *didl_writer, - const char *id, - const char *parent_id, - const char *mime, - const char *title, - const char *path) -{ - GUPnPDIDLLiteResource res; - - gupnp_didl_lite_writer_start_item (didl_writer, - id, - parent_id, - NULL, - FALSE); - - /* Add fields */ - gupnp_didl_lite_writer_add_string (didl_writer, - "title", - GUPNP_DIDL_LITE_WRITER_NAMESPACE_DC, - NULL, - title); - - gupnp_didl_lite_writer_add_string - (didl_writer, - "class", - GUPNP_DIDL_LITE_WRITER_NAMESPACE_UPNP, - NULL, - "object.item.audioItem.musicTrack"); - - gupnp_didl_lite_writer_add_string - (didl_writer, - "album", - GUPNP_DIDL_LITE_WRITER_NAMESPACE_UPNP, - NULL, - "Some album"); - - /* Add resource data */ - gupnp_didl_lite_resource_reset (&res); - - /* URI */ - res.uri = g_strdup_printf ("http://%s:%d%s/%s", - gupnp_context_get_host_ip (context), - gupnp_context_get_port (context), - HOME_DIR_ALIAS, - path); - - /* Protocol info */ - res.protocol_info = g_strdup_printf ("http-get:*:%s:*", mime); - - gupnp_didl_lite_writer_add_res (didl_writer, &res); - - /* Cleanup */ - g_free (res.protocol_info); - g_free (res.uri); - - /* End of item */ - gupnp_didl_lite_writer_end_item (didl_writer); -} - -static char * -browse_direct_children (GUPnPMediaServer *server, guint *num_returned) -{ - GUPnPContext *context; - const char *didl; - char *result; - guint i; - - context = gupnp_device_info_get_context (GUPNP_DEVICE_INFO (server)); - - /* Start DIDL-Lite fragment */ - gupnp_didl_lite_writer_start_didl_lite (server->priv->didl_writer, - NULL, - NULL, - TRUE); - /* Add items */ - for (i = 0; items[i][0]; i++) - add_item (context, - server->priv->didl_writer, - items[i][0], - "0", - items[i][1], - items[i][2], - items[i][3]); - - /* End DIDL-Lite fragment */ - gupnp_didl_lite_writer_end_didl_lite (server->priv->didl_writer); - - /* Retrieve generated string */ - didl = gupnp_didl_lite_writer_get_string (server->priv->didl_writer); - result = g_strdup (didl); - - /* Reset the parser state */ - gupnp_didl_lite_writer_reset (server->priv->didl_writer); - - *num_returned = i; - - return result; -} - -static char * -get_metadata (GUPnPMediaServer *server, - const char *object_id, - guint *num_returned) -{ - GUPnPContext *context; - char *result; - guint i; - - context = gupnp_device_info_get_context (GUPNP_DEVICE_INFO (server)); - - /* Start DIDL-Lite fragment */ - gupnp_didl_lite_writer_start_didl_lite (server->priv->didl_writer, - NULL, - NULL, - TRUE); - *num_returned = 0; - if (strcmp (object_id, "0") == 0) { - add_root_container (server->priv->didl_writer); - - *num_returned = 1; - } else { - /* Find and add the item */ - for (i = 0; items[i][0]; i++) { - if (strcmp (object_id, items[i][0]) == 0) { - add_item (context, - server->priv->didl_writer, - items[i][0], - "0", - items[i][1], - items[i][2], - items[i][3]); - - *num_returned = 1; - - break; - } - } - } - - if (*num_returned != 0) { - const char *didl; - - /* End DIDL-Lite fragment */ - gupnp_didl_lite_writer_end_didl_lite - (server->priv->didl_writer); - - /* Retrieve generated string */ - didl = gupnp_didl_lite_writer_get_string - (server->priv->didl_writer); - result = g_strdup (didl); - } else - result = NULL; - - /* Reset the parser state */ - gupnp_didl_lite_writer_reset (server->priv->didl_writer); - - return result; -} - -/* Browse action implementation */ -void -browse_cb (GUPnPService *service, - GUPnPServiceAction *action, - gpointer user_data) -{ - GUPnPMediaServer *server; - char *object_id, *browse_flag; - gboolean browse_metadata; - char *result; - guint num_returned; - - server = GUPNP_MEDIA_SERVER (user_data); - - /* Handle incoming arguments */ - gupnp_service_action_get (action, - "ObjectID", - G_TYPE_STRING, - &object_id, - "BrowseFlag", - G_TYPE_STRING, - &browse_flag, - NULL); - - /* BrowseFlag */ - if (browse_flag && !strcmp (browse_flag, "BrowseDirectChildren")) { - browse_metadata = FALSE; - } else if (browse_flag && !strcmp (browse_flag, "BrowseMetadata")) { - browse_metadata = TRUE; - } else { - gupnp_service_action_return_error - (action, GUPNP_CONTROL_ERROR_INVALID_ARGS, NULL); - - goto OUT; - } - - /* ObjectID */ - if (!object_id) { - gupnp_service_action_return_error - (action, 701, "No such object"); - - goto OUT; - } - - if (browse_metadata) { - result = get_metadata (server, object_id, &num_returned); - - if (result == NULL) { - gupnp_service_action_return_error - (action, 701, "No such object"); - - goto OUT; - } - } else { - /* We only have a root object */ - if (strcmp (object_id, "0")) { - gupnp_service_action_return_error - (action, 701, "No such object"); - - goto OUT; - } - - result = browse_direct_children (server, &num_returned); - } - - /* Set action return arguments */ - gupnp_service_action_set (action, - "Result", - G_TYPE_STRING, - result, - "NumberReturned", - G_TYPE_UINT, - num_returned, - "TotalMatches", - G_TYPE_UINT, - num_returned, - "UpdateID", - G_TYPE_UINT, - server->priv->system_update_id, - NULL); - - gupnp_service_action_return (action); - - g_free (result); -OUT: - g_free (object_id); -} - -GUPnPMediaServer * -gupnp_media_server_new (GUPnPContext *context, - xmlDoc *description_doc, - const char *relative_location) -{ - GUPnPResourceFactory *factory; - - factory = gupnp_resource_factory_get_default (); - - return g_object_new (GUPNP_TYPE_MEDIA_SERVER, - "context", context, - "resource-factory", factory, - "root-device", NULL, - "description-doc", description_doc, - "relative-location", relative_location, - NULL); -} - diff --git a/src/gupnp-media-server.h b/src/gupnp-media-server.h deleted file mode 100644 index 4f3cbea9..00000000 --- a/src/gupnp-media-server.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2008 Zeeshan Ali <zeenix@gmail.com>. - * Copyright (C) 2007 OpenedHand Ltd. - * - * Author: Zeeshan Ali <zeenix@gmail.com> - * Jorn Baayen <jorn@openedhand.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __GUPNP_MEDIA_SERVER_H__ -#define __GUPNP_MEDIA_SERVER_H__ - -#include <libgupnp/gupnp.h> - -G_BEGIN_DECLS - -GType -gupnp_media_server_get_type (void) G_GNUC_CONST; - -#define GUPNP_TYPE_MEDIA_SERVER \ - (gupnp_media_server_get_type ()) -#define GUPNP_MEDIA_SERVER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - GUPNP_TYPE_MEDIA_SERVER, \ - GUPnPMediaServer)) -#define GUPNP_MEDIA_SERVER_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_CAST ((obj), \ - GUPNP_TYPE_MEDIA_SERVER, \ - GUPnPMediaServerClass)) -#define GUPNP_IS_MEDIA_SERVER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - GUPNP_TYPE_MEDIA_SERVER)) -#define GUPNP_IS_MEDIA_SERVER_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE ((obj), \ - GUPNP_TYPE_MEDIA_SERVER)) -#define GUPNP_MEDIA_SERVER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - GUPNP_TYPE_MEDIA_SERVER, \ - GUPnPMediaServerClass)) - -typedef struct _GUPnPMediaServerPrivate GUPnPMediaServerPrivate; - -typedef struct { - GUPnPRootDevice parent; - - GUPnPMediaServerPrivate *priv; -} GUPnPMediaServer; - -typedef struct { - GUPnPRootDeviceClass parent_class; - - /* future padding */ - void (* _gupnp_reserved1) (void); - void (* _gupnp_reserved2) (void); - void (* _gupnp_reserved3) (void); - void (* _gupnp_reserved4) (void); -} GUPnPMediaServerClass; - -GUPnPMediaServer * -gupnp_media_server_new (GUPnPContext *context, - xmlDoc *description_doc, - const char *relative_location); - -G_END_DECLS - -#endif /* __GUPNP_MEDIA_SERVER_H__ */ diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 677f6b90..00000000 --- a/src/main.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2007 Zeeshan Ali. - * Copyright (C) 2007 OpenedHand Ltd. - * - * Author: Zeeshan Ali <zeenix@gstreamer.net> - * Author: Jorn Baayen <jorn@openedhand.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <stdio.h> -#include <locale.h> -#include <string.h> -#include <gconf/gconf-client.h> -#include <uuid/uuid.h> - -#include "gupnp-media-server.h" - -#define DESC_DOC "xml/description.xml" -#define MODIFIED_DESC_DOC "gupnp-media-server.xml" -#define GCONF_PATH "/apps/gupnp-media-server/" - -static GMainLoop *main_loop; - -/* Copy-paste from gupnp. */ -static xmlNode * -xml_util_get_element (xmlNode *node, - ...) -{ - va_list var_args; - - va_start (var_args, node); - - while (TRUE) { - const char *arg; - - arg = va_arg (var_args, const char *); - if (!arg) - break; - - for (node = node->children; node; node = node->next) - if (!strcmp (arg, (char *) node->name)) - break; - - if (!node) - break; - } - - va_end (var_args); - - return node; -} - -static GUPnPContext * -create_context (GConfClient *gconf_client, - char *desc_path) -{ - GUPnPContext *context; - char *host_ip; - int port; - GError *error; - - error = NULL; - host_ip = gconf_client_get_string (gconf_client, - GCONF_PATH "host-ip", - &error); - if (error) { - g_warning ("%s", error->message); - - g_error_free (error); - } - - error = NULL; - port = gconf_client_get_int (gconf_client, - GCONF_PATH "port", - &error); - if (error) { - g_warning ("%s", error->message); - - g_error_free (error); - } - - error = NULL; - context = gupnp_context_new (NULL, host_ip, port, &error); - - if (host_ip) - g_free (host_ip); - - if (error) { - g_warning ("Error setting up GUPnP context: %s", - error->message); - g_error_free (error); - - return NULL; - } - - /* Host UPnP dir */ - gupnp_context_host_path (context, DATA_DIR, ""); - - /* Host our modified file */ - gupnp_context_host_path (context, desc_path, "/" MODIFIED_DESC_DOC); - - return context; -} - -static char * -get_str_from_gconf (GConfClient *gconf_client, - const char *key, - const char *default_value) -{ - char *str; - - str = gconf_client_get_string (gconf_client, key, NULL); - if (str == NULL) { - GError *error; - - str = g_strdup (default_value); - - error = NULL; - gconf_client_set_string (gconf_client, key, str, &error); - if (error) { - g_warning ("Error setting gconf key '%s': %s.", - key, - error->message); - - g_error_free (error); - g_free (str); - - str = NULL; - } - } - - return str; -} - -/* Fills the description doc @doc with a friendly name, and UDN from gconf. If - * these keys are not present in gconf, they are set with default values */ -static void -set_friendly_name_and_udn (xmlDoc *doc, - GConfClient *gconf_client) -{ - xmlNode *device_element; - xmlNode *element; - char *str, *default_value; - xmlChar *xml_str; - uuid_t id; - - device_element = xml_util_get_element ((xmlNode *) doc, - "root", - "device", - NULL); - if (device_element == NULL) { - g_warning ("Element /root/device not found."); - - return; - } - - /* friendlyName */ - element = xml_util_get_element (device_element, - "friendlyName", - NULL); - if (element == NULL) { - g_warning ("Element /root/device/friendlyName not found."); - - return; - } - - default_value = g_strdup_printf ("%s's GUPnP MediaServer", - g_get_real_name ()); - str = get_str_from_gconf (gconf_client, - GCONF_PATH "friendly-name", - default_value); - g_free (default_value); - - if (str == NULL) { - return; - } - - xml_str = xmlEncodeSpecialChars (doc, (xmlChar *) str); - g_free (str); - - xmlNodeSetContent (element, xml_str); - - xmlFree (xml_str); - - /* UDN */ - element = xml_util_get_element (device_element, - "UDN", - NULL); - if (element == NULL) { - g_warning ("Element /root/device/UDN not found."); - - return; - } - - default_value = g_malloc (64); - strcpy (default_value, "uuid:"); - - /* Generate new UUID */ - uuid_generate (id); - uuid_unparse (id, default_value + 5); - - str = get_str_from_gconf (gconf_client, - GCONF_PATH "UDN", - default_value); - g_free (default_value); - - if (str == NULL) { - return; - } - - xmlNodeSetContent (element, (xmlChar *) str); -} - -static GUPnPMediaServer * -create_ms (void) -{ - GUPnPMediaServer *server; - GUPnPContext *context; - GConfClient *gconf_client; - char *desc_path; - xmlDoc *doc; - FILE *f; - int res; - - /* We store a modified description.xml in the user's config dir */ - desc_path = g_build_filename (g_get_user_config_dir (), - MODIFIED_DESC_DOC, - NULL); - - doc = xmlParseFile (DATA_DIR G_DIR_SEPARATOR_S DESC_DOC); - - if (doc == NULL) - return NULL; - - gconf_client = gconf_client_get_default (); - - /* Modify description.xml to include a UDN and a friendy name */ - set_friendly_name_and_udn (doc, gconf_client); - - /* Save the modified description.xml into the user's config dir. - * We do this so that we can host the modified file, and also to - * make sure the generated UDN stays the same between sessions. */ - f = fopen (desc_path, "w+"); - - if (f != NULL) { - res = xmlDocDump (f, doc); - - fclose (f); - } - - if (f == NULL || res == -1) { - g_critical ("Failed to write modified" - " description.xml to %s.\n", - desc_path); - - g_free (desc_path); - xmlFreeDoc (doc); - g_object_unref (gconf_client); - - return NULL; - } - - /* Set up GUPnP context */ - context = create_context (gconf_client, desc_path); - if (!context) { - g_free (desc_path); - xmlFreeDoc (doc); - g_object_unref (gconf_client); - - return NULL; - } - - g_object_unref (gconf_client); - g_free (desc_path); - - /* Set up the root device */ - server = gupnp_media_server_new (context, - doc, - MODIFIED_DESC_DOC); - g_object_unref (context); - g_object_weak_ref (G_OBJECT (server), - (GWeakNotify) xmlFreeDoc, doc); - - /* Make our device available */ - gupnp_root_device_set_available (GUPNP_ROOT_DEVICE (server), TRUE); - - return server; -} - -int -main (int argc, char **argv) -{ - GUPnPMediaServer *server; - - g_type_init (); - - server = create_ms (); - if (server == NULL) { - return -1; - } - - main_loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (main_loop); - - g_main_loop_unref (main_loop); - g_object_unref (server); - - return 0; -} - |