[gupnp-tools/wip/search: 3/3] wip: search implementation



commit 5892cfb1beba9c6a8a1f1310dda76e0ca5c3881d
Author: Jens Georg <mail jensge org>
Date:   Sun Jun 5 23:26:55 2016 +0200

    wip: search implementation
    
    Signed-off-by: Jens Georg <mail jensge org>

 data/search-dialog.ui     |    6 +-
 src/av-cp/search-dialog.c |  122 ++++++++++++++++++++++++++++++++++++++++++++-
 src/av-cp/server-device.c |   50 ++++++++++++++++++
 src/av-cp/server-device.h |   17 ++++++
 4 files changed, 191 insertions(+), 4 deletions(-)
---
diff --git a/data/search-dialog.ui b/data/search-dialog.ui
index 83ec243..88a17f3 100644
--- a/data/search-dialog.ui
+++ b/data/search-dialog.ui
@@ -2,7 +2,7 @@
 <!-- Generated with glade 3.20.0 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
-  <object class="GtkListStore" id="search-dialog-listview">
+  <object class="GtkListStore" id="search_dialog_liststore">
     <columns>
       <!-- column-name icon -->
       <column type="GdkPixbuf"/>
@@ -52,7 +52,7 @@
             <property name="can_focus">False</property>
             <property name="orientation">vertical</property>
             <child>
-              <object class="GtkEntry">
+              <object class="GtkEntry" id="search_dialog_entry">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="primary_icon_name">edit-find</property>
@@ -75,7 +75,7 @@
                   <object class="GtkTreeView" id="search-dialog-treeview">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="model">search-dialog-listview</property>
+                    <property name="model">search_dialog_liststore</property>
                     <property name="headers_visible">False</property>
                     <child internal-child="selection">
                       <object class="GtkTreeSelection"/>
diff --git a/src/av-cp/search-dialog.c b/src/av-cp/search-dialog.c
index 1bbedf1..ab9b538 100644
--- a/src/av-cp/search-dialog.c
+++ b/src/av-cp/search-dialog.c
@@ -1,5 +1,10 @@
+#include <libgupnp-av/gupnp-av.h>
+
+#include <string.h>
+
 #include "search-dialog.h"
 #include "server-device.h"
+#include "icons.h"
 
 struct _SearchDialog {
         GtkDialog parent;
@@ -10,8 +15,11 @@ struct _SearchDialogClass {
 };
 
 struct _SearchDialogPrivate {
+        GtkListStore *search_dialog_liststore;
+        GtkEntry *search_dialog_entry;
         char *id;
         AVCPMediaServer *server;
+        guint pulse_timer;
 };
 
 typedef struct _SearchDialogPrivate SearchDialogPrivate;
@@ -20,6 +28,41 @@ G_DEFINE_TYPE_WITH_PRIVATE (SearchDialog, search_dialog, GTK_TYPE_DIALOG)
 void
 search_dialog_on_search_activate (SearchDialog *self, GtkEntry *entry);
 
+#define ITEM_CLASS_IMAGE "object.item.imageItem"
+#define ITEM_CLASS_AUDIO "object.item.audioItem"
+#define ITEM_CLASS_VIDEO "object.item.videoItem"
+#define ITEM_CLASS_TEXT  "object.item.textItem"
+
+static GdkPixbuf *
+get_item_icon (GUPnPDIDLLiteObject *object)
+{
+        GdkPixbuf  *icon;
+        const char *class_name;
+
+        class_name = gupnp_didl_lite_object_get_upnp_class (object);
+        if (G_UNLIKELY (class_name == NULL)) {
+                return get_icon_by_id (ICON_FILE);
+        }
+
+        if (g_str_has_prefix (class_name, ITEM_CLASS_IMAGE)) {
+                icon = get_icon_by_id (ICON_IMAGE_ITEM);
+        } else if (g_str_has_prefix (class_name,
+                                    ITEM_CLASS_AUDIO)) {
+                icon = get_icon_by_id (ICON_AUDIO_ITEM);
+        } else if (g_str_has_prefix (class_name,
+                                     ITEM_CLASS_VIDEO)) {
+                icon = get_icon_by_id (ICON_VIDEO_ITEM);
+        } else if (g_str_has_prefix (class_name,
+                                     ITEM_CLASS_TEXT)) {
+                icon = get_icon_by_id (ICON_TEXT_ITEM);
+        } else {
+                icon = get_icon_by_id (ICON_FILE);
+        }
+
+        return icon;
+}
+
+
 static void
 search_dialog_class_init (SearchDialogClass *klass)
 {
@@ -40,6 +83,13 @@ search_dialog_class_init (SearchDialogClass *klass)
         bytes = g_bytes_new_take (data, size);
         gtk_widget_class_set_template (widget_class, bytes);
         g_bytes_unref (bytes);
+
+        gtk_widget_class_bind_template_child_private (widget_class,
+                                                      SearchDialog,
+                                                      search_dialog_liststore);
+        gtk_widget_class_bind_template_child_private (widget_class,
+                                                      SearchDialog,
+                                                      search_dialog_entry);
 }
 
 static void
@@ -48,6 +98,56 @@ search_dialog_init (SearchDialog *self)
         gtk_widget_init_template (GTK_WIDGET (self));
 }
 
+static void
+on_didl_object_available (GUPnPDIDLLiteParser *parser,
+                          GUPnPDIDLLiteObject *object,
+                          gpointer             user_data)
+{
+        SearchDialog *self = SEARCH_DIALOG (user_data);
+        SearchDialogPrivate *priv = search_dialog_get_instance_private (self);
+        GtkTreeIter iter;
+
+        gtk_list_store_insert_with_values (priv->search_dialog_liststore,
+                                           &iter,
+                                           -1,
+                                           0, get_item_icon (object),
+                                           1, gupnp_didl_lite_object_get_title (object),
+                                           -1);
+
+}
+
+static void
+search_dialog_on_search_done (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+        SearchDialog *self = SEARCH_DIALOG (user_data);
+        SearchDialogPrivate *priv = search_dialog_get_instance_private (self);
+
+        GError *error = NULL;
+        char *xml;
+        guint32 total = 0;
+        guint32 returned = 0;
+        GUPnPDIDLLiteParser *parser;
+
+        g_source_remove (priv->pulse_timer);
+
+        if (!av_cp_media_server_search_finish (AV_CP_MEDIA_SERVER (source),
+                                               res,
+                                               &xml,
+                                               &total,
+                                               &returned,
+                                               &error)) {
+                g_critical ("Failed to search: %s", error->message),
+                g_error_free (error);
+        }
+
+        parser = gupnp_didl_lite_parser_new ();
+        g_signal_connect (G_OBJECT (parser), "object-available",
+                G_CALLBACK (on_didl_object_available),
+                self);
+        gupnp_didl_lite_parser_parse_didl (parser, xml, &error);
+        gtk_widget_set_sensitive (GTK_WIDGET (priv->search_dialog_entry), TRUE);
+}
+
 void
 search_dialog_set_server (SearchDialog *self, AVCPMediaServer *server)
 {
@@ -64,10 +164,30 @@ search_dialog_set_container_id (SearchDialog *self, char *id)
         priv->id = id;
 }
 
+static gboolean
+pulse_timer (gpointer user_data)
+{
+        gtk_entry_progress_pulse (GTK_ENTRY (user_data));
+
+        return TRUE;
+}
+
 G_MODULE_EXPORT
 void
 search_dialog_on_search_activate (SearchDialog *self, GtkEntry *entry)
 {
-        g_print ("==> %s\n", gtk_entry_get_text (entry));
+        SearchDialogPrivate *priv = search_dialog_get_instance_private (self);
+        gtk_list_store_clear (priv->search_dialog_liststore);
+        gtk_widget_set_sensitive (GTK_WIDGET (entry), FALSE);
+        priv->pulse_timer = g_timeout_add_seconds (1, pulse_timer, entry);
+
+        av_cp_media_server_search_async (priv->server,
+                                         NULL,
+                                         search_dialog_on_search_done,
+                                         priv->id,
+                                         gtk_entry_get_text (entry),
+                                         0,
+                                         0,
+                                         self);
 }
 
diff --git a/src/av-cp/server-device.c b/src/av-cp/server-device.c
index 2a89e42..5f896ff 100644
--- a/src/av-cp/server-device.c
+++ b/src/av-cp/server-device.c
@@ -556,3 +556,53 @@ av_cp_media_server_browse_metadata_finish (AVCPMediaServer  *self,
 
         return FALSE;
 }
+
+void
+av_cp_media_server_search_async (AVCPMediaServer     *self,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 const char          *container_id,
+                                 const char          *search_criteria,
+                                 guint32              starting_index,
+                                 guint32              requested_count,
+                                 gpointer             user_data)
+{
+        GTask *task = g_task_new (self, cancellable, callback, user_data);
+
+        gupnp_service_proxy_begin_action (self->priv->content_directory,
+                                          "Search",
+                                          av_cp_media_server_on_browse,
+                                          task,
+                                          /* IN args */
+                                          "ContainerID",
+                                          G_TYPE_STRING,
+                                          container_id,
+                                          "SearchCriteria",
+                                          G_TYPE_STRING,
+                                          search_criteria,
+                                          "Filter",
+                                          G_TYPE_STRING,
+                                          "*",
+                                          "StartingIndex",
+                                          G_TYPE_UINT,
+                                          starting_index,
+                                          "RequestedCount",
+                                          G_TYPE_UINT,
+                                          requested_count,
+                                          "SortCriteria",
+                                          G_TYPE_STRING,
+                                          "",
+                                          NULL);
+}
+
+gboolean
+av_cp_media_server_search_finish (AVCPMediaServer  *self,
+                                  GAsyncResult     *result,
+                                  char            **didl_xml,
+                                  guint32          *total_matches,
+                                  guint32          *number_returned,
+                                  GError          **error)
+{
+        return av_cp_media_server_browse_finish (self, result, didl_xml,
+                total_matches, number_returned, error);
+}
diff --git a/src/av-cp/server-device.h b/src/av-cp/server-device.h
index c66fd5f..9f532e4 100644
--- a/src/av-cp/server-device.h
+++ b/src/av-cp/server-device.h
@@ -95,6 +95,23 @@ av_cp_media_server_browse_metadata_finish (AVCPMediaServer  *self,
                                            char            **didl_xml,
                                            GError          **error);
 
+void
+av_cp_media_server_search_async (AVCPMediaServer     *self,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 const char          *container_id,
+                                 const char          *search_criteria,
+                                 guint32              starting_index,
+                                 guint32              requested_count,
+                                 gpointer             user_data);
+gboolean
+av_cp_media_server_search_finish (AVCPMediaServer  *self,
+                                  GAsyncResult     *result,
+                                  char            **didl_xml,
+                                  guint32          *total_matches,
+                                  guint32          *number_returned,
+                                  GError          **error);
+
 G_END_DECLS
 
 #endif /* MEDIA_SERVER_H */


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