diff options
author | Bastien Nocera <hadess@hadess.net> | 2007-10-17 22:36:00 +0000 |
---|---|---|
committer | Bastien Nocera <hadess@src.gnome.org> | 2007-10-17 22:36:00 +0000 |
commit | 6ab17cc9f45185803c6e6666cbf88e44c78ffaaf (patch) | |
tree | 08071694a2f2977b4a8a79973dc87a2ab0214506 | |
parent | 73606d27be2cf981f06a55317d47b0a333bcf13d (diff) |
Add GConf schemas and use those Cache the thumbnail locally, to avoid
2007-10-17 Bastien Nocera <hadess@hadess.net>
* src/plugins/mythtv/Makefile.am:
* src/plugins/mythtv/totem-mythtv.c: (get_thumbnail),
(set_thumbnail_icon), (row_activated_cb), (create_treeview),
(totem_mythtv_list_recordings), (totem_mythtv_update_binfo),
(refresh_cb), (totem_mythtv_plugin_init),
(totem_mythtv_plugin_finalize), (impl_activate), (impl_deactivate):
* src/plugins/mythtv/totem-mythtv.schemas.in:
Add GConf schemas and use those
Cache the thumbnail locally, to avoid getting it again constantly
Add a refresh button, to reload the list of recordings
svn path=/trunk/; revision=4783
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | src/plugins/mythtv/Makefile.am | 17 | ||||
-rw-r--r-- | src/plugins/mythtv/totem-mythtv.c | 264 | ||||
-rw-r--r-- | src/plugins/mythtv/totem-mythtv.schemas.in | 65 |
4 files changed, 276 insertions, 83 deletions
@@ -1,5 +1,18 @@ 2007-10-17 Bastien Nocera <hadess@hadess.net> + * src/plugins/mythtv/Makefile.am: + * src/plugins/mythtv/totem-mythtv.c: (get_thumbnail), + (set_thumbnail_icon), (row_activated_cb), (create_treeview), + (totem_mythtv_list_recordings), (totem_mythtv_update_binfo), + (refresh_cb), (totem_mythtv_plugin_init), + (totem_mythtv_plugin_finalize), (impl_activate), (impl_deactivate): + * src/plugins/mythtv/totem-mythtv.schemas.in: + Add GConf schemas and use those + Cache the thumbnail locally, to avoid getting it again constantly + Add a refresh button, to reload the list of recordings + +2007-10-17 Bastien Nocera <hadess@hadess.net> + * configure.in: Work-around problems with python being installed in /usr/lib64 rather than /usr/lib diff --git a/src/plugins/mythtv/Makefile.am b/src/plugins/mythtv/Makefile.am index df159098..4a2929e2 100644 --- a/src/plugins/mythtv/Makefile.am +++ b/src/plugins/mythtv/Makefile.am @@ -7,6 +7,20 @@ plugin_in_files = mythtv.totem-plugin.in %.totem-plugin: %.totem-plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache +schema_in_files = totem-mythtv.schemas.in +schemadir = $(GCONF_SCHEMA_FILE_DIR) +schema_DATA = $(schema_in_files:.schemas.in=.schemas) +@INTLTOOL_SCHEMAS_RULE@ + +install-data-local: $(schema_DATA) +if GCONF_SCHEMAS_INSTALL + if test -z "$(DESTDIR)" ; then \ + for p in $^ ; do \ + GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $$p 2>&1 > /dev/null; \ + done \ + fi +endif + noinst_DATA = $(plugin_in_files:.totem-plugin.in=.totem-plugin) common_defines = \ @@ -32,9 +46,10 @@ libtotem_mythtv_la_CFLAGS = \ $(DBUS_CFLAGS) \ $(AM_CFLAGS) \ -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/backend \ -I$(top_srcdir)/src/plugins -EXTRA_DIST = $(plugin_in_files) +EXTRA_DIST = $(plugin_in_files) $(schema_in_files) CLEANFILES = $(noinst_DATA) $(BUILT_SOURCES) DISTCLEANFILES = $(plugin_DATA) diff --git a/src/plugins/mythtv/totem-mythtv.c b/src/plugins/mythtv/totem-mythtv.c index 7d27a007..bde54474 100644 --- a/src/plugins/mythtv/totem-mythtv.c +++ b/src/plugins/mythtv/totem-mythtv.c @@ -30,9 +30,11 @@ #include <glib.h> #include <glib-object.h> #include <glib/gi18n-lib.h> +#include <gconf/gconf-client.h> #include <gmodule.h> #include <string.h> +#include "video-utils.h" #include "totem-plugin.h" #include "totem.h" @@ -50,8 +52,17 @@ #define TOTEM_IS_MYTHTV_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TOTEM_TYPE_MYTHTV_PLUGIN)) #define TOTEM_MYTHTV_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TOTEM_TYPE_MYTHTV_PLUGIN, TotemMythtvPluginClass)) +#define CONF_PREFIX "/apps/totem/plugins/totem_mythtv/" +#define CONF_IP CONF_PREFIX "address" +#define CONF_USER CONF_PREFIX "user" +#define CONF_PASSWORD CONF_PREFIX "password" +#define CONF_DATABASE CONF_PREFIX "database" +#define CONF_PORT CONF_PREFIX "port" + enum { FILENAME_COL, + URI_COL, + THUMBNAIL_FILENAME_COL, THUMBNAIL_COL, NAME_COL, DESCRIPTION_COL, @@ -63,9 +74,12 @@ typedef struct TotemPlugin parent; GMythBackendInfo *b_info; + + TotemObject *totem; + GConfClient *client; GtkTreeView *treeview; GtkTreeModel *model; - GtkTreeSelection *selection; + GtkWidget *sidebar; } TotemMythtvPlugin; typedef struct @@ -84,46 +98,6 @@ static void impl_deactivate (TotemPlugin *plugin, TotemObject *totem); TOTEM_PLUGIN_REGISTER(TotemMythtvPlugin, totem_mythtv_plugin) -static void -set_cell_text (GtkTreeViewColumn *column, - GtkCellRenderer *renderer, - GtkTreeModel *model, - GtkTreeIter *iter, - TotemMythtvPlugin *plugin) -{ - GtkTreePath *path; - char *text, *name, *description; - gboolean is_selected; - - gtk_tree_model_get (model, iter, NAME_COL, &name, - DESCRIPTION_COL, &description, - -1); - if (name == NULL) { - g_free (description); - return; - } - - is_selected = gtk_tree_selection_iter_is_selected (plugin->selection, iter); - if (description != NULL && is_selected != FALSE) { - text = g_markup_printf_escaped ("<b>%s</b>\n%s", - name, description); - } else if (is_selected != FALSE) { - text = g_markup_printf_escaped ("<b>%s</b>", name); - } else { - text = g_strdup (name); - } - - g_free (name); - g_free (description); - - g_object_set (renderer, "markup", text, NULL); - g_free (text); - - path = gtk_tree_model_get_path (model, iter); - gtk_tree_model_row_changed (model, path, iter); - gtk_tree_path_free (path); -} - #define MAX_THUMB_SIZE 500 * 1024 * 1024 static GdkPixbuf * @@ -159,6 +133,7 @@ get_thumbnail (TotemMythtvPlugin *plugin, char *fname) } gmyth_file_transfer_close (transfer); + g_object_unref (transfer); g_byte_array_free (data, TRUE); if (res != GMYTH_FILE_READ_OK && res != GMYTH_FILE_READ_EOF) { @@ -178,8 +153,7 @@ get_thumbnail (TotemMythtvPlugin *plugin, char *fname) return pixbuf; } -#define DEFAULT_BIG_THUMB_HEIGHT 50 -#define DEFAULT_SMALL_THUMB_HEIGHT 25 +#define THUMB_HEIGHT 32 static void set_thumbnail_icon (GtkTreeViewColumn *column, @@ -191,32 +165,50 @@ set_thumbnail_icon (GtkTreeViewColumn *column, GdkPixbuf *pixbuf, *scaled; int width, height; GtkTreePath *path; + char *thumb_fname; + + /* If we already have a pixbuf, use it */ + gtk_tree_model_get (model, iter, + THUMBNAIL_COL, &pixbuf, -1); + if (pixbuf != NULL) { + g_object_set (renderer, "pixbuf", pixbuf, NULL); + g_object_unref (pixbuf); + return; + } - gtk_tree_model_get (model, iter, THUMBNAIL_COL, &pixbuf, -1); - if (pixbuf == NULL) { - char *fname, *thumb_fname; + /* If there's no backend info, no point in continuing */ + if (plugin->b_info == NULL) + return; - gtk_tree_model_get (model, iter, FILENAME_COL, &fname, -1); - if (fname == NULL) - return; - thumb_fname = g_strdup_printf ("%s.png", fname); + /* Filename is zero'ed when we've tried getting the + * thumbnail once already */ + gtk_tree_model_get (model, iter, + THUMBNAIL_FILENAME_COL, &thumb_fname, -1); + if (thumb_fname == NULL) + return; + pixbuf = get_thumbnail (plugin, thumb_fname); + g_free (thumb_fname); - pixbuf = get_thumbnail (plugin, thumb_fname); + /* No pixbuf */ + if (pixbuf == NULL) { gtk_list_store_set (GTK_LIST_STORE (model), iter, - THUMBNAIL_COL, pixbuf, -1); - } - - if (pixbuf == NULL) + THUMBNAIL_FILENAME_COL, NULL, -1); + g_object_set (renderer, "icon-name", "video", NULL); + path = gtk_tree_model_get_path (model, iter); + gtk_tree_model_row_changed (model, path, iter); + gtk_tree_path_free (path); return; + } - height = gtk_tree_selection_iter_is_selected (plugin->selection, iter) - ? DEFAULT_BIG_THUMB_HEIGHT : DEFAULT_SMALL_THUMB_HEIGHT; + height = THUMB_HEIGHT; width = gdk_pixbuf_get_width (pixbuf) * height / gdk_pixbuf_get_height (pixbuf); scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR); g_object_unref (pixbuf); + gtk_list_store_set (GTK_LIST_STORE (model), iter, + THUMBNAIL_COL, scaled, + THUMBNAIL_FILENAME_COL, NULL, -1); g_object_set (renderer, "pixbuf", scaled, NULL); - g_object_unref (scaled); path = gtk_tree_model_get_path (model, iter); gtk_tree_model_row_changed (model, path, iter); @@ -224,6 +216,25 @@ set_thumbnail_icon (GtkTreeViewColumn *column, } static void +row_activated_cb (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + TotemMythtvPlugin *plugin) +{ + GtkTreeIter iter; + char *uri; + + if (gtk_tree_model_get_iter (plugin->model, &iter, path) == FALSE) + g_return_if_reached (); + + gtk_tree_model_get (plugin->model, &iter, + URI_COL, &uri, -1); + g_return_if_fail (uri != NULL); + + totem_action_set_mrl_and_play (plugin->totem, uri); +} + +static void create_treeview (TotemMythtvPlugin *plugin) { GtkCellRenderer *renderer; @@ -231,14 +242,19 @@ create_treeview (TotemMythtvPlugin *plugin) /* Treeview and model */ plugin->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS, - G_TYPE_STRING, - G_TYPE_OBJECT, - G_TYPE_STRING, - G_TYPE_STRING)); + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_OBJECT, + G_TYPE_STRING, + G_TYPE_STRING)); plugin->treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (plugin->model)); g_object_unref (G_OBJECT(plugin->model)); gtk_tree_view_set_headers_visible (plugin->treeview, FALSE); + g_signal_connect (G_OBJECT (plugin->treeview), "row-activated", + G_CALLBACK (row_activated_cb), plugin); + /* Playing pix */ renderer = gtk_cell_renderer_pixbuf_new (); column = gtk_tree_view_column_new (); @@ -253,19 +269,19 @@ create_treeview (TotemMythtvPlugin *plugin) renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, "xalign", 0.0, NULL); - gtk_tree_view_column_set_cell_data_func (column, renderer, - (GtkTreeCellDataFunc) set_cell_text, - plugin, NULL); - - plugin->selection = gtk_tree_view_get_selection (plugin->treeview); + gtk_tree_view_column_set_attributes (column, renderer, + "text", NAME_COL, NULL); } static void -list_recordings (TotemMythtvPlugin *plugin) +totem_mythtv_list_recordings (TotemMythtvPlugin *plugin) { GMythScheduler *scheduler; GList *list, *l; + if (plugin->b_info == NULL) + return; + scheduler = gmyth_scheduler_new(); if (gmyth_scheduler_connect_with_timeout(scheduler, plugin->b_info, 5) == FALSE) { @@ -291,18 +307,28 @@ list_recordings (TotemMythtvPlugin *plugin) (plugin->b_info, recorded_info->basename->str)) { GtkTreeIter iter; char *full_name = NULL; + char *thumb_fname, *uri; if (recorded_info->subtitle->str != NULL && recorded_info->subtitle->str[0] != '\0') full_name = g_strdup_printf ("%s - %s", recorded_info->title->str, recorded_info->subtitle->str); + thumb_fname = g_strdup_printf ("%s.png", recorded_info->basename->str); + uri = g_strdup_printf ("myth://%s:%d/%s", + plugin->b_info->hostname, + plugin->b_info->port, + recorded_info->basename->str); gtk_list_store_insert_with_values (GTK_LIST_STORE (plugin->model), &iter, G_MAXINT32, FILENAME_COL, recorded_info->basename->str, + URI_COL, uri, + THUMBNAIL_FILENAME_COL, thumb_fname, NAME_COL, full_name ? full_name : recorded_info->title->str, DESCRIPTION_COL, recorded_info->description->str, -1); g_free (full_name); + g_free (thumb_fname); + g_free (uri); } gmyth_recorded_info_free(recorded_info); } @@ -323,24 +349,78 @@ totem_mythtv_plugin_class_init (TotemMythtvPluginClass *klass) } static void +totem_mythtv_update_binfo (TotemMythtvPlugin *plugin) +{ + char *address, *user, *password, *database; + int port; + + if (plugin->b_info != NULL) { + //FIXME why would this crash? + //g_object_unref (plugin->b_info); + plugin->b_info = NULL; + } + + if (plugin->client == NULL) + plugin->client = gconf_client_get_default (); + if (plugin->client == NULL) + return; + + address = gconf_client_get_string (plugin->client, CONF_IP, NULL); + /* No address? */ + if (address == NULL || address[0] == '\0') + return; + + user = gconf_client_get_string (plugin->client, CONF_USER, NULL); + if (user == NULL || user[0] == '\0') + user = g_strdup ("mythtv"); + password = gconf_client_get_string (plugin->client, CONF_PASSWORD, NULL); + if (password == NULL || password[0] == '\0') + password = g_strdup ("mythtv"); + database = gconf_client_get_string (plugin->client, CONF_DATABASE, NULL); + if (database == NULL || database[0] == '\0') + database = g_strdup ("mythconverg"); + port = gconf_client_get_int (plugin->client, CONF_PORT, NULL); + if (port == 0) + port = 6543; + + plugin->b_info = gmyth_backend_info_new_full (address, + user, + password, + database, + port); +} + +static void +refresh_cb (GtkWidget *button, TotemMythtvPlugin *plugin) +{ + gtk_widget_set_sensitive (button, FALSE); + totem_mythtv_update_binfo (plugin); + gtk_list_store_clear (GTK_LIST_STORE (plugin->model)); + totem_gdk_window_set_waiting_cursor (plugin->sidebar->window); + totem_mythtv_list_recordings (plugin); + gdk_window_set_cursor (plugin->sidebar->window, NULL); + gtk_widget_set_sensitive (button, TRUE); +} + +static void totem_mythtv_plugin_init (TotemMythtvPlugin *plugin) { - //FIXME obviously - plugin->b_info = gmyth_backend_info_new_full ("192.168.1.5", - "mythtv", - "mythtv", - "mythconverg", - 6543); + totem_mythtv_update_binfo (plugin); } static void totem_mythtv_plugin_finalize (GObject *object) { TotemMythtvPlugin *plugin = TOTEM_MYTHTV_PLUGIN(object); + if (plugin->b_info != NULL) { g_object_unref (plugin->b_info); plugin->b_info = NULL; } + if (plugin->client != NULL) { + g_object_unref (plugin->client); + plugin->client = NULL; + } G_OBJECT_CLASS (totem_mythtv_plugin_parent_class)->finalize (object); } @@ -350,20 +430,33 @@ impl_activate (TotemPlugin *plugin, TotemObject *totem, GError **error) { - GtkWidget *viewport; + GtkWidget *viewport, *box, *button; TotemMythtvPlugin *tm = TOTEM_MYTHTV_PLUGIN(plugin); + tm->totem = g_object_ref (totem); + + box = gtk_vbox_new (FALSE, 6); + button = gtk_button_new_from_stock (GTK_STOCK_REFRESH); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (refresh_cb), plugin); viewport = gtk_viewport_new (NULL, NULL); create_treeview (tm); - gtk_container_add (GTK_CONTAINER(viewport), GTK_WIDGET (tm->treeview)); - gtk_widget_show_all (viewport); + gtk_container_add (GTK_CONTAINER (viewport), GTK_WIDGET (tm->treeview)); + gtk_container_add (GTK_CONTAINER (box), viewport); + gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 0); + gtk_widget_show_all (box); totem_add_sidebar_page (totem, "mythtv", _("MythTV Recordings"), - viewport); - g_message ("Just added the mythtv sidebar"); + box); + + tm->sidebar = g_object_ref (box); + + totem_mythtv_update_binfo (TOTEM_MYTHTV_PLUGIN(plugin)); - list_recordings (TOTEM_MYTHTV_PLUGIN(plugin)); + totem_gdk_window_set_waiting_cursor (box->window); + totem_mythtv_list_recordings (TOTEM_MYTHTV_PLUGIN(plugin)); + gdk_window_set_cursor (box->window, NULL); return TRUE; } @@ -372,8 +465,15 @@ static void impl_deactivate (TotemPlugin *plugin, TotemObject *totem) { + TotemMythtvPlugin *tm = TOTEM_MYTHTV_PLUGIN(plugin); + + g_object_unref (tm->sidebar); totem_remove_sidebar_page (totem, "mythtv"); - //FIXME disconnect from stuff - g_message ("Just removed the mythtv sidebar"); + + if (tm && tm->client != NULL) { + g_object_unref (tm->client); + tm->client = NULL; + } + g_object_unref (totem); } diff --git a/src/plugins/mythtv/totem-mythtv.schemas.in b/src/plugins/mythtv/totem-mythtv.schemas.in new file mode 100644 index 00000000..8dd9fdf1 --- /dev/null +++ b/src/plugins/mythtv/totem-mythtv.schemas.in @@ -0,0 +1,65 @@ +<gconfschemafile> + <schemalist> + + <schema> + <key>/schemas/apps/totem/plugins/totem_mythtv/address</key> + <applyto>/apps/totem/plugins/totem_mythtv/address</applyto> + <owner>totem</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>IP address of the local MythTV server</short> + <long> </long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/totem/plugins/totem_mythtv/user</key> + <applyto>/apps/totem/plugins/totem_mythtv/user</applyto> + <owner>totem</owner> + <type>string</type> + <default>mythtv</default> + <locale name="C"> + <short>Username to access the local MythTV server</short> + <long> </long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/totem/plugins/totem_mythtv/password</key> + <applyto>/apps/totem/plugins/totem_mythtv/password</applyto> + <owner>totem</owner> + <type>string</type> + <default>mythtv</default> + <locale name="C"> + <short>Password to access the local MythTV server</short> + <long> </long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/totem/plugins/totem_mythtv/database</key> + <applyto>/apps/totem/plugins/totem_mythtv/database</applyto> + <owner>totem</owner> + <type>string</type> + <default>mythconverg</default> + <locale name="C"> + <short>Name of the database for the local MythTV server</short> + <long> </long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/totem/plugins/totem_mythtv/port</key> + <applyto>/apps/totem/plugins/totem_mythtv/port</applyto> + <owner>totem</owner> + <type>int</type> + <default>6543</default> + <locale name="C"> + <short>Port to access the local MythTV server</short> + <long> </long> + </locale> + </schema> + + </schemalist> +</gconfschemafile> |