[rygel] ruih: Initial RUIH service implementation



commit 4e132cb0d4a88ff8f525653e7e11517fd58ef76d
Author: Scott Deboy <sdeboy secondstryke com>
Date:   Tue Dec 3 18:35:00 2013 +0000

    ruih: Initial RUIH service implementation
    
    Initial implementation of RemoteUIServer:1 spec

 common.am                                          |   15 ++
 configure.ac                                       |   14 ++
 data/rygel.conf                                    |    4 +
 data/xml/Makefile.am                               |    3 +
 data/xml/RemoteUIServerService.xml.in              |   47 +++++
 data/xml/RuihServer2.xml.in.in                     |   20 ++
 data/xml/UIList.xml.in                             |   14 ++
 examples/Makefile.am                               |    9 +
 examples/standalone-ruih.c                         |   61 ++++++
 rygel-ruih-1.0.pc.in                               |   12 ++
 src/Makefile.am                                    |    2 +-
 src/librygel-ruih/Makefile.am                      |   39 ++++
 src/librygel-ruih/filelist.am                      |   15 ++
 src/librygel-ruih/rygel-ruih-2.0.deps              |    5 +
 src/librygel-ruih/rygel-ruih-filter-entry.vala     |   74 ++++++++
 src/librygel-ruih/rygel-ruih-icon-elem.vala        |  110 +++++++++++
 src/librygel-ruih/rygel-ruih-protocol-elem.vala    |  148 +++++++++++++++
 src/librygel-ruih/rygel-ruih-server-plugin.vala    |   69 +++++++
 src/librygel-ruih/rygel-ruih-server.vala           |   61 ++++++
 src/librygel-ruih/rygel-ruih-service-error.vala    |   34 ++++
 src/librygel-ruih/rygel-ruih-service.vala          |  126 +++++++++++++
 src/librygel-ruih/rygel-ruih-servicemanager.vala   |  195 ++++++++++++++++++++
 src/librygel-ruih/rygel-ruih-ui-elem.vala          |  174 +++++++++++++++++
 src/librygel-ruih/rygel-ruih-ui-listing.vala       |   74 ++++++++
 .../rygel-ruih-wildcard-filter-entry.vala          |   37 ++++
 src/plugins/Makefile.am                            |    7 +-
 src/plugins/ruih/Makefile.am                       |   22 +++
 src/plugins/ruih/ruih.plugin.in                    |    7 +
 src/plugins/ruih/rygel-ruih-module.vala            |   41 ++++
 src/plugins/ruih/rygel-ruih-plugin.vala            |   46 +++++
 30 files changed, 1483 insertions(+), 2 deletions(-)
---
diff --git a/common.am b/common.am
index da84740..53b7ebc 100644
--- a/common.am
+++ b/common.am
@@ -26,6 +26,7 @@ bigicondir = $(shareddir)/icons/120x120
 librygelcoredir = $(top_srcdir)/src/librygel-core
 librygelserverdir = $(top_srcdir)/src/librygel-server
 librygelrendererdir = $(top_srcdir)/src/librygel-renderer
+librygelruihdir = $(top_srcdir)/src/librygel-ruih
 
 MAINTAINERCLEANFILES = Makefile.in
 
@@ -92,6 +93,20 @@ RYGEL_COMMON_LIBRYGEL_SERVER_LIBS = \
        $(RYGEL_COMMON_LIBRYGEL_CORE_LIBS) \
        $(top_builddir)/src/librygel-server/librygel-server-2.4.la
 
+RYGEL_COMMON_LIBRYGEL_RUIH_VALAFLAGS = \
+        --vapidir=$(top_builddir)/src/librygel-ruih \
+        --pkg rygel-ruih-2.0 \
+        $(RYGEL_COMMON_LIBRYGEL_CORE_VALAFLAGS)
+
+RYGEL_COMMON_LIBRYGEL_RUIH_CFLAGS = \
+        $(RYGEL_COMMON_LIBRYGEL_CORE_CFLAGS) \
+        -I$(top_builddir)/src/librygel-ruih \
+        -I$(top_srcdir)/src/librygel-ruih
+
+RYGEL_COMMON_LIBRYGEL_RUIH_LIBS = \
+        $(RYGEL_COMMON_LIBRYGEL_CORE_LIBS) \
+        $(top_builddir)/src/librygel-ruih/librygel-ruih-2.0.la
+
 RYGEL_COMMON_BUILD_CONFIG_VALAFLAGS = \
        --vapidir=$(librygelcoredir) \
        --pkg rygel-build-config
diff --git a/configure.ac b/configure.ac
index 324dd56..756b2a2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -152,6 +152,16 @@ AS_IF([test "x$enable_mediathek_plugin" = "xyes"],
                        libxml-2.0 >= $LIBXML_REQUIRED])
   ])
 
+RYGEL_ADD_PLUGIN([ruih],[Ruih],[yes])
+AS_IF([test "x$enable_ruih_plugin" = "xyes"],
+  [
+    PKG_CHECK_MODULES([RYGEL_PLUGIN_RUIH_DEPS],
+                      [$RYGEL_COMMON_MODULES
+                       gio-2.0 >= $GIO_REQUIRED
+                       libsoup-2.4 >= $LIBSOUP_REQUIRED
+                       libxml-2.0 >= $LIBXML_REQUIRED])
+  ])
+
 AS_IF([test "x$with_media_engine" = "xgstreamer"],
       [
         RYGEL_ADD_PLUGIN([playbin],[GStreamer playbin],[yes])
@@ -205,6 +215,7 @@ dnl Explicitly add stamp files for targets that are not plugins
 RYGEL_ADD_STAMP([src/librygel-core/librygel_core_2_4_la_vala.stamp])
 RYGEL_ADD_STAMP([src/librygel-server/librygel_server_2_4_la_vala.stamp])
 RYGEL_ADD_STAMP([src/librygel-renderer/librygel_renderer_2_4_la_vala.stamp])
+RYGEL_ADD_STAMP([src/librygel-ruih/librygel_ruih_2_0_la_vala.stamp])
 RYGEL_ADD_STAMP([src/rygel/rygel_vala.stamp])
 RYGEL_ADD_STAMP([src/ui/rygel_preferences_vala.stamp])
 RYGEL_ADD_STAMP([src/media-engines/simple/librygel_media_engine_simple_la_vala.stamp])
@@ -423,6 +434,7 @@ src/librygel-core/Makefile
 src/librygel-renderer/Makefile
 src/librygel-renderer-gst/Makefile
 src/librygel-server/Makefile
+src/librygel-ruih/Makefile
 src/rygel/Makefile
 src/ui/Makefile
 src/media-engines/Makefile
@@ -434,6 +446,7 @@ src/plugins/Makefile
 data/Makefile
 data/xml/Makefile
 data/xml/MediaServer3.xml.in
+data/xml/RuihServer2.xml.in
 data/xml/MediaRenderer2.xml.in
 data/icons/Makefile
 data/icons/32x32/Makefile
@@ -454,6 +467,7 @@ rygel-core-2.4.pc
 rygel-renderer-2.4.pc
 rygel-server-2.4.pc
 rygel-renderer-gst-2.4.pc
+rygel-ruih-1.0.pc
 tests/Makefile
 examples/Makefile
 examples/renderer-plugins/Makefile
diff --git a/data/rygel.conf b/data/rygel.conf
index 2293326..d8e53e9 100644
--- a/data/rygel.conf
+++ b/data/rygel.conf
@@ -158,3 +158,7 @@ enabled=false
 
 [External]
 enabled=false
+
+[Ruih]
+enabled=false
+title=Rygel Remote UI Server
diff --git a/data/xml/Makefile.am b/data/xml/Makefile.am
index 6f32b19..c0f9f29 100644
--- a/data/xml/Makefile.am
+++ b/data/xml/Makefile.am
@@ -1,10 +1,13 @@
 xml_in_files = MediaServer3.xml.in \
                MediaRenderer2.xml.in \
+               RuihServer2.xml.in \
                ContentDirectory.xml.in \
                ContentDirectory-NoTrack.xml.in \
                ConnectionManager.xml.in \
+               RemoteUIServerService.xml.in \
                AVTransport2.xml.in \
                RenderingControl2.xml.in \
+               UIList.xml.in \
                BasicManagement2.xml.in \
                X_MS_MediaReceiverRegistrar1.xml.in
 
diff --git a/data/xml/RemoteUIServerService.xml.in b/data/xml/RemoteUIServerService.xml.in
new file mode 100644
index 0000000..7986a6c
--- /dev/null
+++ b/data/xml/RemoteUIServerService.xml.in
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+   <specVersion>
+      <major>1</major>
+      <minor>0</minor>
+   </specVersion>
+   <actionList>
+      <action>
+         <name>GetCompatibleUIs</name>
+         <argumentList>
+            <argument>
+               <name>InputDeviceProfile</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_DeviceProfile</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>UIFilter</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_String</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>UIListing</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_CompatibleUIs</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+   </actionList>
+   <serviceStateTable>
+      <stateVariable sendEvents="yes">
+         <name>UIListingUpdate</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_DeviceProfile</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_CompatibleUIs</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+          <name>A_ARG_TYPE_String</name>
+          <dataType>string</dataType>
+      </stateVariable>
+   </serviceStateTable>
+</scpd>
diff --git a/data/xml/RuihServer2.xml.in.in b/data/xml/RuihServer2.xml.in.in
new file mode 100644
index 0000000..1867762
--- /dev/null
+++ b/data/xml/RuihServer2.xml.in.in
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <device>
+    <deviceType>urn:schemas-upnp-org:device:RemoteUIServerDevice:1</deviceType>
+    <UDN></UDN>
+    <friendlyName></friendlyName>
+    <manufacturer>Rygel Developers.</manufacturer>
+    <manufacturerURL>@PACKAGE_URL@</manufacturerURL>
+    <modelName>Rygel</modelName>
+    <modelNumber>@VERSION@</modelNumber>
+    <serialNumber>0000001</serialNumber>
+    <serviceList>
+    </serviceList>
+    <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">+RUIHSRC+/DMS-1.50</dlna:X_DLNADOC>
+  </device>
+</root>
diff --git a/data/xml/UIList.xml.in b/data/xml/UIList.xml.in
new file mode 100644
index 0000000..0d7af80
--- /dev/null
+++ b/data/xml/UIList.xml.in
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uilist xmlns="urn:schemas-upnp-org:remoteui:uilist-1-0"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="urn:schemas-upnp-org:remoteui:uilist-1-0 CompatibleUIs.xsd">
+  <ui>
+   <uiID>1234-9876-1265-8758</uiID>
+   <name>CableLabs Program Guide</name>
+   <description>CableLabs Program Guide application</description>
+   <fork>true</fork>
+   <lifetime>-1</lifetime>
+   <protocol shortName="DLNA-HTML5-1.0">
+     <uri>http://192.168.0.100:4004/index.html</uri>
+   </protocol>
+ </ui>
+</uilist>
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 7f7a7a1..0271f53 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -21,6 +21,15 @@ standalone_server_LDADD = \
        $(EXAMPLE_DEPS_LIBS) \
        $(RYGEL_COMMON_LIBRYGEL_SERVER_LIBS)
 
+noinst_PROGRAMS += standalone-ruih
+standalone_ruih_SOURCES = standalone-ruih.c
+standalone_ruih_CFLAGS = \
+        $(EXAMPLE_DEPS_CFLAGS) \
+        $(RYGEL_COMMON_LIBRYGEL_RUIH_CFLAGS)
+standalone_ruih_LDADD = \
+        $(EXAMPLE_DEPS_LIBS) \
+        $(RYGEL_COMMON_LIBRYGEL_RUIH_LIBS)
+
 if HAVE_GSTREAMER
 
 noinst_PROGRAMS += standalone-renderer-gst
diff --git a/examples/standalone-ruih.c b/examples/standalone-ruih.c
new file mode 100644
index 0000000..45bdb2a
--- /dev/null
+++ b/examples/standalone-ruih.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Demo application for librygel-ruih.
+ *
+ * Creates a stand-alone UPnP ruih server
+ *
+ * Usage:
+ *   standalone-ruih
+ *
+ * The server listens on wlan0 and eth0 by default.
+ */
+
+#include <gio/gio.h>
+#include <rygel-ruih.h>
+#include <rygel-core.h>
+
+int main (int argc, char *argv[])
+{
+    RygelRuihServer *server;
+    int i;
+    GMainLoop *loop;
+    GError *error = NULL;
+
+    g_type_init ();
+
+    g_set_application_name ("Standalone-Ruih");
+
+    server = rygel_ruih_server_new ("RUIH sample server",
+                                     RYGEL_PLUGIN_CAPABILITIES_NONE);
+    rygel_media_device_add_interface (RYGEL_MEDIA_DEVICE (server), "eth0");
+    rygel_media_device_add_interface (RYGEL_MEDIA_DEVICE (server), "wlan0");
+
+    loop = g_main_loop_new (NULL, FALSE);
+    g_main_loop_run (loop);
+}
diff --git a/rygel-ruih-1.0.pc.in b/rygel-ruih-1.0.pc.in
new file mode 100644
index 0000000..638a07f
--- /dev/null
+++ b/rygel-ruih-1.0.pc.in
@@ -0,0 +1,12 @@
+prefix= prefix@
+exec_prefix= exec_prefix@
+libdir= libdir@
+includedir= includedir@
+
+Name: rygel-ruih-1.0
+Description: GNOME (Mobile) UPnP/DLNA RUIH server library
+Version: @VERSION@
+Libs: -L${libdir} -lrygel-ruih-1.0
+Cflags: -I${includedir}/rygel-2.2
+Requires: gupnp-av-1.0 gee-0.8 rygel-core-2.2
+Requires.Private: uuid gmodule-2.0
diff --git a/src/Makefile.am b/src/Makefile.am
index c3737aa..31b44eb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = librygel-core librygel-renderer librygel-server
+SUBDIRS = librygel-core librygel-renderer librygel-server librygel-ruih
 
 if HAVE_GSTREAMER
 SUBDIRS += librygel-renderer-gst
diff --git a/src/librygel-ruih/Makefile.am b/src/librygel-ruih/Makefile.am
new file mode 100644
index 0000000..4943a1e
--- /dev/null
+++ b/src/librygel-ruih/Makefile.am
@@ -0,0 +1,39 @@
+include ../../common.am
+include $(srcdir)/filelist.am
+
+librygel_ruih_includedir=$(includedir)/rygel-2.2
+librygel_ruih_include_HEADERS = rygel-ruih.h
+
+lib_LTLIBRARIES = librygel-ruih-2.0.la
+
+LIBRYGEL_RUIH_VERSION=1:0:0
+
+librygel_ruih_2_0_la_SOURCES = \
+        $(LIBRYGEL_RUIH_VAPI_SOURCE_FILES) \
+        $(LIBRYGEL_RUIH_NONVAPI_SOURCE_FILES)
+
+librygel_ruih_2_0_la_VALAFLAGS = \
+        -H rygel-ruih.h --library=rygel-ruih-2.0 \
+        $(LIBRYGEL_RUIH_DEPS_VALAFLAGS) \
+        $(RYGEL_COMMON_LIBRYGEL_CORE_VALAFLAGS) \
+        $(RYGEL_COMMON_VALAFLAGS)
+
+librygel_ruih_2_0_la_CFLAGS = \
+        $(LIBRYGEL_SERVER_DEPS_CFLAGS) \
+        $(RYGEL_COMMON_LIBRYGEL_CORE_CFLAGS) \
+        -DENGINE_DIR='"$(enginedir)"' \
+        -DG_LOG_DOMAIN=\"Rygel\"
+librygel_ruih_2_0_la_LIBADD = \
+        $(LIBRYGEL_RUIH_DEPS_LIBS) \
+        $(RYGEL_COMMON_LIBRYGEL_CORE_LIBS)
+
+librygel_ruih_2_0_la_LDFLAGS = \
+        $(RYGEL_DATA_DIR_DEFINES) \
+        -version-info $(LIBRYGEL_RUIH_VERSION)
+
+vapidir = $(VAPIDIR)
+vapi_DATA = rygel-ruih-2.0.vapi rygel-ruih-2.0.deps
+
+rygel-ruih.h rygel-ruih-2.0.vapi: librygel_ruih_2_0_la_vala.stamp
+
+EXTRA_DIST = rygel-ruih.h rygel-ruih-2.0.vapi rygel-ruih-2.0.deps
diff --git a/src/librygel-ruih/filelist.am b/src/librygel-ruih/filelist.am
new file mode 100644
index 0000000..73bce70
--- /dev/null
+++ b/src/librygel-ruih/filelist.am
@@ -0,0 +1,15 @@
+
+LIBRYGEL_RUIH_VAPI_SOURCE_FILES = \
+    rygel-ruih-filter-entry.vala \
+    rygel-ruih-icon-elem.vala \
+    rygel-ruih-protocol-elem.vala \
+    rygel-ruih-server-plugin.vala \
+    rygel-ruih-server.vala  \
+    rygel-ruih-service.vala \
+    rygel-ruih-service-error.vala \
+    rygel-ruih-servicemanager.vala \
+    rygel-ruih-ui-elem.vala \
+    rygel-ruih-ui-listing.vala \
+    rygel-ruih-wildcard-filter-entry.vala
+
+LIBRYGEL_RUIH_NONVAPI_SOURCE_FILES =
diff --git a/src/librygel-ruih/rygel-ruih-2.0.deps b/src/librygel-ruih/rygel-ruih-2.0.deps
new file mode 100644
index 0000000..86fd022
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-2.0.deps
@@ -0,0 +1,5 @@
+gee-0.8
+gupnp-1.0
+gio-2.0
+rygel-core-2.2
+gupnp-av-1.0
diff --git a/src/librygel-ruih/rygel-ruih-filter-entry.vala b/src/librygel-ruih/rygel-ruih-filter-entry.vala
new file mode 100644
index 0000000..3b14b34
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-filter-entry.vala
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+protected class FilterEntry {
+    private static const string LIFETIME = "lifetime";
+
+    string entry_name = null;
+    string entry_value = null;
+
+    public FilterEntry (string name, string value) {
+        string temp = name;
+        // Get rid of extra "  in name
+        temp = temp.replace ("\"", "");
+        entry_name = temp;
+
+        // Get rid of extra " in value
+        temp = value;
+        temp = temp.replace ("\"", "");
+
+        // Escape regular expression symbols
+        temp = Regex.escape_string (temp);
+        // Convert escaped * to .* for regular expression matching (only in value)
+        temp = temp.replace ("\\*", ".*");
+        entry_value = temp;
+    }
+
+    public bool matches (string name, string value) {
+        if (entry_name == null && entry_value == null) {
+            return false;
+        }
+
+        if (entry_name == name || entry_name == "*") {
+            if (entry_value != null) {
+                if (entry_name == LIFETIME) {
+                    // Lifetime value can be negative as well.
+                    if (int.parse (entry_value) == int.parse (value)) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+                var result = Regex.match_simple (entry_value, value,
+                                                 RegexCompileFlags.CASELESS);
+                return result;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-icon-elem.vala b/src/librygel-ruih/rygel-ruih-icon-elem.vala
new file mode 100644
index 0000000..d30b946
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-icon-elem.vala
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+using Gee;
+using Xml;
+
+protected class IconElem : UIListing {
+    private static const string MIMETYPE = "mimetype";
+    private static const string WIDTH = "width";
+    private static const string HEIGHT = "height";
+    private static const string DEPTH = "depth";
+    private static const string URL = "url";
+
+    // optional attributes
+    private string mime_type = null;
+    private string width = null;
+    private string height = null;
+    private string depth = null;
+    private string url = null;
+
+    public IconElem (Xml.Node* node) throws Rygel.RuihServiceError {
+        if (node == null) {
+            throw new Rygel.RuihServiceError.OPERATION_REJECTED ("Unable to parse Icon data - null");
+        }
+        // Invalid XML Handling?
+        for (Xml.Node* child_node = node->children; child_node != null; child_node = child_node->next) {
+            if (child_node->type == Xml.ElementType.TEXT_NODE) {
+                // ignore text nodes
+                continue;
+            }
+            string node_name = child_node->name;
+            switch (node_name) {
+            case MIMETYPE:
+                this.mime_type = child_node->get_content ();
+                break;
+            case WIDTH:
+                this.width = child_node->get_content ();
+                break;
+            case HEIGHT:
+                this.height = child_node->get_content ();
+                break;
+            case DEPTH:
+                this.depth = child_node->get_content ();
+                break;
+            case URL:
+                this.url = child_node->get_content ();
+                break;
+            default:
+                throw new Rygel.RuihServiceError.OPERATION_REJECTED ("Unable to parse Icon data - unexpected 
node: " + node_name);
+            }
+        }
+    }
+
+    public override bool match (Gee.ArrayList<ProtocolElem> protocols, Gee.ArrayList<FilterEntry> filters) {
+        return true;
+    }
+
+    public override string to_ui_listing (Gee.ArrayList<FilterEntry> filters) {
+        HashMap<string, string> elements = new HashMap<string, string> ();
+        if ((this.mime_type != null) && (filters_match (filters, ICON + "@" + MIMETYPE, this.mime_type))) {
+            elements.set (MIMETYPE, this.mime_type);
+        }
+        if ((this.width != null) && (filters_match (filters, ICON + "@" + WIDTH, this.width))) {
+            elements.set (WIDTH, this.width);
+        }
+        if ((this.height != null) && (filters_match (filters, ICON + "@" + HEIGHT, this.height))) {
+            elements.set (HEIGHT, this.height);
+        }
+        if ((this.depth != null) && (filters_match (filters, ICON + "@" + DEPTH, this.depth))) {
+            elements.set (DEPTH, this.depth);
+        }
+        if ((this.url != null) && (filters_match (filters, ICON + "@" + URL, this.url))) {
+            elements.set (URL, this.url);
+        }
+
+        if (elements.size > 0) {
+            StringBuilder sb = new StringBuilder ();
+            sb.append ("<" + ICON + ">\n");
+            sb.append (to_xml (elements));
+            sb.append ("</" + ICON + ">\n");
+            return sb.str;
+        }
+        return "";
+    }
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-protocol-elem.vala b/src/librygel-ruih/rygel-ruih-protocol-elem.vala
new file mode 100644
index 0000000..c5eed14
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-protocol-elem.vala
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+using Gee;
+using Xml;
+
+protected class ProtocolElem : UIListing {
+    private string short_name = null;
+    private string protocol_info = null;
+    private Gee.ArrayList<string> uris;
+
+    public ProtocolElem (Xml.Node* node) throws Rygel.RuihServiceError {
+        this.uris = new ArrayList<string> ();
+
+        if (node == null) {
+            throw new Rygel.RuihServiceError.OPERATION_REJECTED
+                ("Unable to parse Protocol data - null");
+        }
+        for (Xml.Attr* prop = node->properties; prop != null;
+            prop = prop->next) {
+            string attr_name = prop->name;
+            switch (attr_name) {
+            case SHORT_NAME:
+                this.short_name = prop->children->content;
+                break;
+            default:
+                throw new Rygel.RuihServiceError.OPERATION_REJECTED
+                        ("Unable to parse Protocol data - unexpected attribute: "
+                         + attr_name);
+            }
+        }
+
+        for (Xml.Node* child_node = node->children; child_node != null;
+            child_node = child_node->next) {
+            if (child_node->type == Xml.ElementType.TEXT_NODE) {
+                // ignore text nodes
+                continue;
+            }
+            string node_name = child_node->name;
+            switch (node_name) {
+            case URI:
+                this.uris.add (child_node->get_content ());
+                break;
+            case PROTOCOL_INFO:
+                this.protocol_info = child_node->get_content ();
+                break;
+            default:
+                throw new Rygel.RuihServiceError.OPERATION_REJECTED
+                        ("Unable to parse Protocol data - unexpected node: " + node_name);
+            }
+        }
+    }
+
+    public string get_short_name () {
+        return this.short_name;
+    }
+
+    public string get_protocol_info () {
+        return this.protocol_info;
+    }
+
+    public override bool match (Gee.ArrayList<ProtocolElem> protocols,
+                                Gee.ArrayList filters) {
+        if (protocols == null || protocols.size == 0) {
+            return true;
+        }
+
+        foreach (ProtocolElem i in protocols) {
+            ProtocolElem proto = (ProtocolElem)i;
+            if (this.short_name == proto.get_short_name ()) {
+                // Optionally if a protocolInfo is specified
+                // match on that as well.
+                if (proto.get_protocol_info () != null &&
+                        proto.get_protocol_info ()._strip ().length > 0) {
+                    if (proto.get_protocol_info () == this.protocol_info) {
+                        return true;
+                    }
+                } else {
+                   return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public override string to_ui_listing (Gee.ArrayList<FilterEntry>
+                                          filters) {
+        bool matches = false;
+        HashMap<string, string> elements = new
+            HashMap<string, string> ();
+        if ((this.short_name != null) && (filters_match (filters,
+            SHORT_NAME, this.short_name)))
+        {
+            matches = true;
+        }
+
+        if ((this.protocol_info != null) && (filters_match
+            (filters, PROTOCOL_INFO, this.protocol_info)))
+        {
+            elements.set (PROTOCOL_INFO, this.protocol_info);
+            matches = true;
+        }
+
+        StringBuilder sb = new StringBuilder ();
+        if (matches) {
+            sb.append ("<" + PROTOCOL + " " + SHORT_NAME
+                + "=\""  + this.short_name + "\">\n");
+            if (this.uris.size > 0)
+            {
+                foreach (string i in this.uris)
+                {
+                    sb.append ("<").append (URI).append (">")
+                    .append (i)
+                    .append ("</").append (URI).append (">\n");
+                }
+            }
+            sb.append (to_xml (elements));
+            sb.append ("</" + PROTOCOL + ">\n");
+        }
+        return sb.str;
+    }
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-server-plugin.vala b/src/librygel-ruih/rygel-ruih-server-plugin.vala
new file mode 100644
index 0000000..a3c1184
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-server-plugin.vala
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * This is the base class for every Rygel UPnP Ruih plugin.
+ *
+ * This class is useful when implementing Rygel Ruih Server plugins.
+ *
+ */
+public class Rygel.RuihServerPlugin : Rygel.Plugin {
+    private static const string RUIH_SERVER_DESC_PATH =
+                                BuildConfig.DATA_DIR +
+                                "/xml/RuihServer2.xml";
+    private static const string RUIH = "urn:schemas-upnp-org:device:RemoteUIServer";
+
+
+    /**
+     * Create an instance of the plugin.
+     *
+     * @param name The non-human-readable name for the plugin, used in UPnP messages and in the Rygel 
configuration file.
+     * @param title An optional human-readable name (friendlyName) of the UPnP renderer provided by the 
plugin. If the title is empty then the name will be used.
+     * @param description An optional human-readable description (modelDescription) of the UPnP renderer 
provided by the plugin.
+     */
+    public RuihServerPlugin (string  name,
+                                string? title,
+                                string? description = null,
+                                PluginCapabilities capabilities =
+                                        PluginCapabilities.NONE) {
+        Object (desc_path : RUIH_SERVER_DESC_PATH,
+                name : name,
+                title : title,
+                description : description,
+                capabilities : capabilities);
+    }
+
+    public override void constructed () {
+        base.constructed ();
+
+        var resource = new ResourceInfo (RuihService.UPNP_ID,
+                                         RuihService.UPNP_TYPE,
+                                         RuihService.DESCRIPTION_PATH,
+                                         typeof (RuihService));
+        this.add_resource (resource);
+    }
+}
diff --git a/src/librygel-ruih/rygel-ruih-server.vala b/src/librygel-ruih/rygel-ruih-server.vala
new file mode 100644
index 0000000..eb4760c
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-server.vala
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+internal class Plugin : Rygel.RuihServerPlugin {
+    public Plugin (Rygel.PluginCapabilities capabilities) {
+        base ("LibRygelRuih", "LibRygelRuih", null, capabilities);
+    }
+}
+
+/**
+ * This class may be used to implement in-process UPnP RUIH servers.
+ *
+ * Call rygel_media_device_add_interface () on the RygelRuihServer to allow it
+ * to serve requests via that network interface.
+ *
+ */
+public class Rygel.RuihServer : MediaDevice {
+
+    /**
+     * Create a RuihServer to serve the UIs.
+     */
+    public RuihServer (string title,
+                        PluginCapabilities capabilities =
+                                        PluginCapabilities.NONE) {
+        Object (title: title,
+                capabilities: capabilities);
+    }
+
+    public override void constructed () {
+        base.constructed ();
+
+        if (this.plugin == null) {
+            this.plugin = new global::Plugin (this.capabilities);
+        }
+        this.plugin.title = this.title;
+    }
+}
diff --git a/src/librygel-ruih/rygel-ruih-service-error.vala b/src/librygel-ruih/rygel-ruih-service-error.vala
new file mode 100644
index 0000000..638a8d5
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-service-error.vala
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* These error codes are returned to applications and
+    must be defined in the spec.
+ */
+public errordomain Rygel.RuihServiceError {
+    OPERATION_REJECTED = 701,
+    INVALID_FILTER = 702
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-service.vala b/src/librygel-ruih/rygel-ruih-service.vala
new file mode 100644
index 0000000..749f7e0
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-service.vala
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+using GUPnP;
+using Gee;
+
+/**
+ * Basic implementation of UPnP RemoteUIServer service version 1.
+ */
+internal class Rygel.RuihService: Service {
+    public const string UPNP_ID =
+                     "urn:upnp-org:serviceId:RemoteUIServer";
+    public const string UPNP_TYPE =
+                    "urn:schemas-upnp-org:service:RemoteUIServer:1";
+    public const string DESCRIPTION_PATH =
+                    "xml/RemoteUIServerService.xml";
+    public const string UI_LISTING_FILE_NAME = "UIList.xml";
+
+    internal static Cancellable cancellable;
+    private static string ui_listing_full_path;
+    private static FileMonitor ui_file_monitor;
+    private static RuihServiceManager ruih_manager;
+
+    static construct {
+        cancellable = new Cancellable ();
+        var ui_listing_directory = Path.build_filename (
+                Environment.get_user_config_dir (), "Rygel");
+        ui_listing_full_path = Path.build_filename (ui_listing_directory,
+                UI_LISTING_FILE_NAME);
+        DirUtils.create_with_parents (ui_listing_directory, 0755);
+        ruih_manager = new RuihServiceManager ();
+
+        try {
+            ruih_manager.set_ui_list (ui_listing_full_path);
+            var ui_file = File.new_for_path (ui_listing_full_path);
+            ui_file_monitor = ui_file.monitor_file (FileMonitorFlags.NONE,
+                                                        cancellable);
+            ui_file_monitor.changed.connect ((src, dest, event) => {
+                try {
+                        ruih_manager.set_ui_list (ui_listing_full_path);
+                }
+                catch (RuihServiceError e) {
+                   error ("Failed to set UIList for file %s - %s\n", ui_listing_full_path,
+                         e.message);
+                }
+            });
+        }
+        catch (Rygel.RuihServiceError e) {
+            error ("Failed to set initial UI list for file %s - %s\n",
+                  ui_listing_full_path, e.message);
+        }
+        catch (GLib.IOError e) {
+            error ("Failed to monitor the file %s - %s\n", ui_listing_full_path,
+                  e.message);
+        }
+    }
+
+    public override void constructed () {
+        base.constructed ();
+
+        this.query_variable["UIListingUpdate"].connect
+            (this.query_ui_listing);
+
+        this.action_invoked["GetCompatibleUIs"].connect
+            (this.get_compatible_uis_cb);
+    }
+
+    ~RuihService () {
+        cancellable.cancel ();
+    }
+
+    /* Browse action implementation */
+    private void get_compatible_uis_cb (Service       content_dir,
+                            ServiceAction action) {
+
+        string input_device_profile, input_ui_filter;
+        action.get ("InputDeviceProfile", typeof (string),
+                    out input_device_profile);
+        action.get ("UIFilter", typeof (string), out input_ui_filter);
+
+        try
+        {
+            string compat_ui = ruih_manager.get_compatible_uis
+                (input_device_profile, input_ui_filter);
+
+            action.set ("UIListing", typeof (string), compat_ui);
+            action.return ();
+        }
+        catch (RuihServiceError e)
+        {
+            action.return_error (e.code, e.message);
+        }
+    }
+
+    private void query_ui_listing (Service   ruih_service,
+                                 string    variable,
+                                 ref GLib.Value   value) {
+        value.init (typeof (string));
+        value.set_string ("");
+    }
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-servicemanager.vala 
b/src/librygel-ruih/rygel-ruih-servicemanager.vala
new file mode 100644
index 0000000..0ad7963
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-servicemanager.vala
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+using GUPnP;
+using Gee;
+using Xml;
+using GLib;
+
+public class Rygel.RuihServiceManager
+{
+    private static const string DEVICEPROFILE = "deviceprofile";
+    private static const string PROTOCOL = "protocol";
+    private static const string PROTOCOL_INFO = "protocolInfo";
+    private static const string SHORT_NAME = "shortName";
+    private static const string UI = "ui";
+    private static const string UILIST = "uilist";
+
+    private static string PRE_RESULT =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+        + "<" + UILIST + " xmlns=\"urn:schemas-upnp-org:remoteui:uilist-1-0\" "
+        + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"; "
+        + "xsi:schemaLocation=\"urn:schemas-upnp-org:remoteui:uilist-1-0 CompatibleUIs.xsd\">\n";
+
+    private static string POST_RESULT = "</" + UILIST + ">\n";
+    private ArrayList<UIElem> ui_list;
+    private Object object = null;
+
+    public void set_ui_list (string ui_list_file_path) throws RuihServiceError {
+        lock (object) {
+            this.ui_list = new ArrayList<UIElem> ();
+            // Empty internal data
+            if (ui_list_file_path == null) {
+                return;
+            }
+
+            Xml.Doc* doc = Parser.parse_file (ui_list_file_path);
+            if (doc == null) {
+                throw new RuihServiceError.OPERATION_REJECTED
+                    ("Unable to parse UI list file: " + ui_list_file_path);
+            }
+
+            Xml.Node* ui_list_node = doc->get_root_element ();
+            if (ui_list_node != null &&
+                ui_list_node->name == UILIST)
+            {
+                for (Xml.Node* child_node = ui_list_node->children;
+                     child_node != null; child_node = child_node->next)
+                {
+                    if (child_node->name == UI)
+                    {
+                        this.ui_list.add (new UIElem (child_node));
+                    }
+                }
+            }
+            delete doc;
+        }
+    }
+
+    public string get_compatible_uis (string deviceProfile, string filter)
+        throws RuihServiceError {
+        lock (object) {
+            ArrayList<ProtocolElem> protocols = new ArrayList<ProtocolElem> ();
+            ArrayList<FilterEntry> filter_entries = new ArrayList<FilterEntry> ();
+            Xml.Node* device_profile_node = null;
+            Xml.Doc* doc = null;
+            // Parse if there is device info
+
+            if (deviceProfile != null && deviceProfile.length > 0) {
+                doc = Parser.parse_memory (deviceProfile,
+                                                    deviceProfile.length);
+                if (doc == null) {
+                    throw new RuihServiceError.OPERATION_REJECTED
+                        ("Unable to parse device profile data: " + deviceProfile);
+                }
+                device_profile_node = doc->get_root_element ();
+            }
+
+            // If inputDeviceProfile and filter are empty
+            // just display all HTML5 UI elements.
+            // This is a change from the UPNP-defined behavior
+            if (device_profile_node == null && filter == "") {
+                filter_entries.add (new FilterEntry (SHORT_NAME, "*HTML5*"));
+            }
+
+            // Parse device info to create protocols
+            if (device_profile_node != null) {
+                if (device_profile_node->name == DEVICEPROFILE) {
+                    for (Xml.Node* child_node = device_profile_node->children;
+                         child_node != null; child_node = child_node->next) {
+                        if (child_node->type == Xml.ElementType.TEXT_NODE) {
+                            // ignore text nodes
+                            continue;
+                        }
+                        if (child_node->name == PROTOCOL) {
+                            // Get shortName attribute
+                            for (Xml.Attr* prop = child_node->properties; prop != null;
+                                 prop = prop->next) {
+                                if (prop->name == SHORT_NAME &&
+                                    prop->children->content != null) {
+                                    filter_entries.add (new FilterEntry (SHORT_NAME,
+                                                                         prop->children->content));
+                                }
+                            }
+                        }
+                        if (child_node->name == PROTOCOL_INFO &&
+                            child_node->content != null) {
+                            filter_entries.add (new FilterEntry (PROTOCOL_INFO,
+                                                                child_node->content));
+                        }
+                    }// for
+                }// if
+                delete doc;
+            } // outer if
+
+            if (filter.length > 0) {
+                if (filter == "*" || filter == "\"*\"") {
+                    // Wildcard filter entry
+                    filter_entries.add (new WildCardFilterEntry ());
+                } else {
+                    // Check if the input UIFilter is in the right format.
+                    if ((filter.get_char (0) != '"') ||
+                        ((filter.get_char (filter.length - 1) != '"')
+                        && (filter.get_char (filter.length - 1) != ','))
+                        ||  (!(filter.contains (",")) && filter.contains (";"))) {
+                        throw new RuihServiceError.INVALID_FILTER
+                            ("Invalid filter: " + filter);
+                    }
+
+                    string[] entries = filter.split (",");
+                    foreach (unowned string str in entries) {
+                        // separator with no content, ignore
+                        if (str.length == 0) {
+                            continue;
+                        }
+                        string value = null;
+                        // string off quotes
+                        var name_value = str.split ("=");
+                        if (name_value != null &&
+                            name_value.length == 2 &&
+                            name_value[1] != null &&
+                            name_value[1].length > 2) {
+                            if (name_value[1].get_char (0) == '"' &&
+                               name_value[1].get_char
+                               (name_value[1].length - 1) == '"') {
+                                value = name_value[1].substring
+                                    (1, name_value[1].length - 1);
+                                filter_entries.add (new FilterEntry
+                                                    (name_value[0], value));
+                            }
+                        }
+                    }
+                }
+            }
+
+            // Generate result XML with or without protocols
+            StringBuilder result = new StringBuilder (PRE_RESULT);
+
+            if (this.ui_list != null && this.ui_list.size > 0) {
+                foreach (UIElem i in this.ui_list) {
+                    UIElem ui = (UIElem)i;
+                    if (ui.match (protocols , filter_entries)) {
+                        result.append (ui.to_ui_listing (filter_entries));
+                    }
+                }
+            }
+            result.append (POST_RESULT);
+            return result.str;
+        }
+    }
+} // RygelServiceManager class
diff --git a/src/librygel-ruih/rygel-ruih-ui-elem.vala b/src/librygel-ruih/rygel-ruih-ui-elem.vala
new file mode 100644
index 0000000..1c737f1
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-ui-elem.vala
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+using Gee;
+using Xml;
+
+protected class UIElem : UIListing
+{
+    private string id = null;
+    private string name = null;
+    private string description = null;
+    private string fork = null;
+    private string lifetime = null;
+
+    private Gee.ArrayList<IconElem> icons ;
+    private Gee.ArrayList<ProtocolElem> protocols;
+
+    public UIElem (Xml.Node* node) throws Rygel.RuihServiceError
+    {
+        if (node == null)
+        {
+            throw new Rygel.RuihServiceError.OPERATION_REJECTED
+                ("Unable to parse UI data - null");
+        }
+
+        this.icons = new ArrayList<IconElem> ();
+        this.protocols = new ArrayList<ProtocolElem> ();
+
+        // invalid XML exception?
+        for (Xml.Node* child_node = node->children; child_node != null;
+             child_node = child_node->next)
+        {
+            if (child_node->type == Xml.ElementType.TEXT_NODE) {
+                // ignore text nodes
+                continue;
+            }
+            string node_name = child_node->name;
+            switch (node_name) {
+            case UIID:
+                this.id = child_node->get_content ();
+                break;
+            case NAME:
+                this.name = child_node->get_content ();
+                break;
+            case DESCRIPTION:
+                this.description = child_node->get_content ();
+                break;
+            case ICONLIST:
+                for (Xml.Node* icon_node = child_node->children;
+                    icon_node != null; icon_node = icon_node->next)
+                {
+                    if (icon_node->name == ICON)
+                    {
+                        this.icons.add (new IconElem (icon_node));
+                    }
+                }
+                break;
+            case FORK:
+                this.fork = child_node->get_content ();
+                break;
+            case LIFETIME:
+                this.lifetime = child_node->get_content ();
+                break;
+            case PROTOCOL:
+                this.protocols.add (new ProtocolElem (child_node));
+                break;
+            default:
+                throw new Rygel.RuihServiceError.OPERATION_REJECTED
+                        ("Unable to parse UI data - unexpected node: "
+                         + node_name);
+            }
+        }
+    }
+
+    public override bool match (Gee.ArrayList<ProtocolElem> protocol_elements,
+                               Gee.ArrayList<FilterEntry> filters) {
+        if (protocol_elements == null || protocol_elements.size == 0) {
+            return true;
+        }
+
+        foreach (ProtocolElem prot in protocol_elements) {
+            ProtocolElem proto = (ProtocolElem)prot;
+            if (proto.match (this.protocols, filters)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public override string to_ui_listing (Gee.ArrayList<FilterEntry> filters) {
+        HashMap<string, string> elements =
+            new HashMap<string, string> ();
+        bool match = false;
+        elements.set (UIID, this.id);
+        elements.set (NAME, this.name);
+
+        if ((this.name != null) && (filters_match (filters, NAME, this.name))) {
+            match = true;
+        }
+        if ((this.description != null) && (filters_match (filters, DESCRIPTION,
+                                                         this.description))) {
+            elements.set (DESCRIPTION, this.description);
+            match = true;
+        }
+        if ((this.fork != null) && (filters_match (filters, FORK, this.fork))) {
+            elements.set (FORK, this.fork);
+            match = true;
+        }
+        if ((this.lifetime != null) && (filters_match (filters, LIFETIME,
+                                                      this.lifetime))) {
+            elements.set (LIFETIME, this.lifetime);
+            match = true;
+        }
+
+        StringBuilder sb = new StringBuilder ("<" + UI + ">\n");
+        sb.append (to_xml (elements));
+
+        StringBuilder icon_sb = new StringBuilder ();
+        foreach (IconElem i in this.icons) {
+            icon_sb.append (i.to_ui_listing (filters));
+        }
+
+        // Only display list if there is something to display
+        if (icon_sb.str.length > 0) {
+            match = true;
+            sb.append ("<" + ICONLIST + ">\n");
+            sb.append (icon_sb.str);
+            sb.append ("</" + ICONLIST + ">\n");
+        }
+        StringBuilder protocol_sb = new StringBuilder ();
+        if (this.protocols.size > 0) {
+            foreach (ProtocolElem i in this.protocols) {
+                protocol_sb.append (i.to_ui_listing (filters));
+            }
+            if (protocol_sb.str.length > 0) {
+                match = true;
+                sb.append (protocol_sb.str);
+            }
+        }
+
+        sb.append ("</" + UI + ">\n");
+        if (match) {
+            return sb.str;
+        } else {
+            return "";
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-ui-listing.vala b/src/librygel-ruih/rygel-ruih-ui-listing.vala
new file mode 100644
index 0000000..5a95754
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-ui-listing.vala
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+using Gee;
+
+public abstract class UIListing
+{
+    protected static const string DESCRIPTION = "description";
+    protected static const string FORK = "fork";
+    protected static const string ICON = "icon";
+    protected static const string ICONLIST = "iconList";
+    protected static const string LIFETIME = "lifetime";
+    protected static const string NAME = "name";
+    protected static const string PROTOCOL = "protocol";
+    protected static const string PROTOCOL_INFO = "protocolInfo";
+    protected static const string SHORT_NAME = "shortName";
+    protected static const string UI = "ui";
+    protected static const string URI = "uri";
+    protected static const string UIID = "uiID";
+
+    public abstract bool match (Gee.ArrayList<ProtocolElem> protocols,
+                               Gee.ArrayList<FilterEntry> filters);
+    public abstract string to_ui_listing (Gee.ArrayList<FilterEntry> filters);
+
+    public string to_xml (Gee.HashMap<string, string> hashMap) {
+        StringBuilder sb = new StringBuilder ();
+        foreach (Map.Entry<string, string> e in hashMap.entries) {
+            sb.append ("<").append (e.key).append (">")
+            .append (e.value)
+            .append ("</").append (e.key).append (">\n");
+        }
+        return sb.str;
+    }
+
+    // Convenience method to avoid a lot of inline loops
+    public bool filters_match (Gee.ArrayList<FilterEntry> filters,
+                               string name, string value) {
+        if (filters != null && name != null && value != null) {
+            foreach (FilterEntry fil in filters) {
+                FilterEntry entry = (FilterEntry)fil;
+
+                if ((entry != null) && (entry.matches (name, value))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/src/librygel-ruih/rygel-ruih-wildcard-filter-entry.vala 
b/src/librygel-ruih/rygel-ruih-wildcard-filter-entry.vala
new file mode 100644
index 0000000..3b0aeaa
--- /dev/null
+++ b/src/librygel-ruih/rygel-ruih-wildcard-filter-entry.vala
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Neha Shanbhag <N Shanbhag cablelabs com>
+ */
+
+protected class WildCardFilterEntry : FilterEntry {
+    public WildCardFilterEntry () {
+        base ("*","*");
+    }
+
+    public new bool matches (string name, string value) {
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 3c1365c..d116f09 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -26,13 +26,18 @@ if BUILD_PLAYBIN_PLUGIN
 PLAYBIN = playbin
 endif
 
+if BUILD_RUIH_PLUGIN
+RUIH = ruih
+endif
+
 SUBDIRS = $(TRACKER_PLUGIN) \
          $(MEDIATHEK_PLUGIN) \
          $(MEDIA_EXPORT_PLUGIN) \
          $(EXTERNAL_PLUGIN) \
          $(MPRIS_PLUGIN) \
          $(GST_LAUNCH_PLUGIN) \
-          $(PLAYBIN)
+          $(PLAYBIN) \
+          $(RUIH)
 
 MAINTAINERCLEANFILES = Makefile.in
 
diff --git a/src/plugins/ruih/Makefile.am b/src/plugins/ruih/Makefile.am
new file mode 100644
index 0000000..aa2f654
--- /dev/null
+++ b/src/plugins/ruih/Makefile.am
@@ -0,0 +1,22 @@
+include $(top_srcdir)/common.am
+
+plugin_LTLIBRARIES = librygel-ruih.la
+plugin_DATA = ruih.plugin
+
+librygel_ruih_la_SOURCES = rygel-ruih-module.vala rygel-ruih-plugin.vala
+librygel_ruih_la_VALAFLAGS = \
+        --pkg rygel-ruih-2.0 \
+        --vapidir $(top_srcdir)/src/librygel-ruih \
+        $(RYGEL_COMMON_LIBRYGEL_RUIH_VALAFLAGS) \
+        $(RYGEL_COMMON_VALAFLAGS)
+librygel_ruih_la_CFLAGS = \
+        $(RYGEL_PLUGIN_RUIH_DEPS_CFLAGS) \
+        $(RYGEL_COMMON_LIBRYGEL_RUIH_CFLAGS) \
+        -DG_LOG_DOMAIN='"Ruih"'
+librygel_ruih_la_LIBADD = \
+        $(RYGEL_PLUGIN_RUIH_DEPS_LIBS) \
+        $(RYGEL_COMMON_LIBRYGEL_RUIH_LIBS)
+librygel_ruih_la_LDFLAGS = \
+        $(RYGEL_PLUGIN_LINKER_FLAGS)
+
+EXTRA_DIST = ruih.plugin.in
diff --git a/src/plugins/ruih/ruih.plugin.in b/src/plugins/ruih/ruih.plugin.in
new file mode 100644
index 0000000..f3933e0
--- /dev/null
+++ b/src/plugins/ruih/ruih.plugin.in
@@ -0,0 +1,7 @@
+[Plugin]
+Version = @VERSION@
+Module = ruih
+Name = Ruih
+License = LGPL
+Description = A Remote UI Server
+Copyright = Copyright © Rygel maintainers
diff --git a/src/plugins/ruih/rygel-ruih-module.vala b/src/plugins/ruih/rygel-ruih-module.vala
new file mode 100644
index 0000000..0dce4d9
--- /dev/null
+++ b/src/plugins/ruih/rygel-ruih-module.vala
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+using Rygel;
+
+public void module_init (PluginLoader loader) {
+    if (loader.plugin_disabled (Ruih.Plugin.NAME)) {
+        message ("Plugin '%s' disabled by user, ignoring..",
+                 Ruih.Plugin.NAME);
+
+        return;
+    }
+
+    var plugin = new Ruih.Plugin ();
+
+    loader.add_plugin (plugin);
+}
diff --git a/src/plugins/ruih/rygel-ruih-plugin.vala b/src/plugins/ruih/rygel-ruih-plugin.vala
new file mode 100644
index 0000000..72aa03a
--- /dev/null
+++ b/src/plugins/ruih/rygel-ruih-plugin.vala
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ * Contact: http://www.cablelabs.com/
+ *
+ * Rygel 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.
+ *
+ * You should have received a copy of the GNU Lesser 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+using Rygel;
+using Gee;
+
+internal class Rygel.Ruih.Plugin : Rygel.RuihServerPlugin {
+    public const string NAME = "Ruih";
+
+    public Plugin () {
+        string title;
+        try {
+            title = MetaConfig.get_default().get_string (Plugin.NAME,"title");
+        } catch(Error err) {
+            warning ("Setting default name for Ruih");
+            title = "CableLabs CVP-2 RemoteUIServer";
+        }
+        base (Plugin.NAME, _(title));
+    }
+
+}


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