summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2007-10-17 22:36:00 +0000
committerBastien Nocera <hadess@src.gnome.org>2007-10-17 22:36:00 +0000
commit6ab17cc9f45185803c6e6666cbf88e44c78ffaaf (patch)
tree08071694a2f2977b4a8a79973dc87a2ab0214506
parent73606d27be2cf981f06a55317d47b0a333bcf13d (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--ChangeLog13
-rw-r--r--src/plugins/mythtv/Makefile.am17
-rw-r--r--src/plugins/mythtv/totem-mythtv.c264
-rw-r--r--src/plugins/mythtv/totem-mythtv.schemas.in65
4 files changed, 276 insertions, 83 deletions
diff --git a/ChangeLog b/ChangeLog
index 8e6921b2..28b4fb0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>