[gupnp-tools/wip/search: 3/3] wip: search implementation
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp-tools/wip/search: 3/3] wip: search implementation
- Date: Sun, 5 Jun 2016 21:27:41 +0000 (UTC)
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]