[gthumb/ext: 17/18] added ability to save the video screenshot
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb/ext: 17/18] added ability to save the video screenshot
- Date: Fri, 6 Nov 2009 00:17:02 +0000 (UTC)
commit e22ba0bb8e1577002bb9a17777659084ea3d2d9d
Author: Paolo Bacchilega <paobac src gnome org>
Date: Fri Nov 6 01:10:03 2009 +0100
added ability to save the video screenshot
disable the screenshot command if no video is available
extensions/gstreamer/Makefile.am | 3 +-
extensions/gstreamer/data/Makefile.am | 16 +
.../gstreamer/data/gthumb-gstreamer.schemas.in | 17 +
extensions/gstreamer/data/ui/save-screenshot.ui | 171 ++++++++++
extensions/gstreamer/gth-media-viewer-page.c | 349 ++++++++++++++++----
extensions/gstreamer/preferences.h | 28 ++
extensions/image_viewer/gth-image-viewer-page.c | 158 +--------
extensions/image_viewer/preferences.h | 2 +-
gthumb/Makefile.am | 2 +
gthumb/glib-utils.c | 24 ++
gthumb/glib-utils.h | 1 +
gthumb/gth-file-chooser-dialog.c | 276 ++++++++++++++++
gthumb/gth-file-chooser-dialog.h | 61 ++++
13 files changed, 903 insertions(+), 205 deletions(-)
---
diff --git a/extensions/gstreamer/Makefile.am b/extensions/gstreamer/Makefile.am
index b7b1c92..3b2b559 100644
--- a/extensions/gstreamer/Makefile.am
+++ b/extensions/gstreamer/Makefile.am
@@ -14,7 +14,8 @@ libgstreamer_la_SOURCES = \
gth-media-viewer-page.h \
gth-metadata-provider-gstreamer.c \
gth-metadata-provider-gstreamer.h \
- main.c
+ main.c \
+ preferences.h
libgstreamer_la_CPPFLAGS = $(GTHUMB_CFLAGS) $(GSTREAMER_CFLAGS) $(DISABLE_DEPRECATED) $(WARNINGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
libgstreamer_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
diff --git a/extensions/gstreamer/data/Makefile.am b/extensions/gstreamer/data/Makefile.am
index 4d5385d..65c0e27 100644
--- a/extensions/gstreamer/data/Makefile.am
+++ b/extensions/gstreamer/data/Makefile.am
@@ -1,2 +1,18 @@
SUBDIRS = ui
+
+schemadir = @GCONF_SCHEMA_FILE_DIR@
+schema_in_files = gthumb-gstreamer.schemas.in
+schema_DATA = $(schema_in_files:.schemas.in=.schemas)
+
+ INTLTOOL_SCHEMAS_RULE@
+
+if GCONF_SCHEMAS_INSTALL
+install-data-local:
+ GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(top_builddir)/extensions/image_viewer/data/$(schema_DATA)
+endif
+
+EXTRA_DIST = $(schema_in_files)
+
+CLEANFILES = $(schema_DATA)
+
-include $(top_srcdir)/git.mk
diff --git a/extensions/gstreamer/data/gthumb-gstreamer.schemas.in b/extensions/gstreamer/data/gthumb-gstreamer.schemas.in
new file mode 100644
index 0000000..0fe9cf1
--- /dev/null
+++ b/extensions/gstreamer/data/gthumb-gstreamer.schemas.in
@@ -0,0 +1,17 @@
+<gconfschemafile>
+ <schemalist>
+
+ <schema>
+ <key>/schemas/apps/gthumb/ext/gstreamer/screenshot_location</key>
+ <applyto>/apps/gthumb/ext/gstreamer/screenshot_location</applyto>
+ <owner>gthumb</owner>
+ <type>string</type>
+ <default>~</default>
+ <locale name="C">
+ <short></short>
+ <long></long>
+ </locale>
+ </schema>
+
+ </schemalist>
+</gconfschemafile>
diff --git a/extensions/gstreamer/data/ui/save-screenshot.ui b/extensions/gstreamer/data/ui/save-screenshot.ui
new file mode 100644
index 0000000..1a254c3
--- /dev/null
+++ b/extensions/gstreamer/data/ui/save-screenshot.ui
@@ -0,0 +1,171 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkDialog" id="save_screenshot_dialog">
+ <property name="border_width">5</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">normal</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="preview_scrolledwindow">
+ <property name="width_request">240</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Name:</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Destination:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="filename_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="destination_filechooserbutton">
+ <property name="visible">True</property>
+ <property name="local_only">False</property>
+ <property name="create_folders">False</property>
+ <property name="action">select-folder</property>
+ <property name="title" translatable="yes">Choose a folder</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok_button">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">cancel_button</action-widget>
+ <action-widget response="0">ok_button</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/extensions/gstreamer/gth-media-viewer-page.c b/extensions/gstreamer/gth-media-viewer-page.c
index 365dae3..699b7a9 100644
--- a/extensions/gstreamer/gth-media-viewer-page.c
+++ b/extensions/gstreamer/gth-media-viewer-page.c
@@ -29,11 +29,13 @@
#include <gthumb.h>
#include "gstreamer-utils.h"
#include "gth-media-viewer-page.h"
+#include "preferences.h"
#define GTH_MEDIA_VIEWER_PAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_MEDIA_VIEWER_PAGE, GthMediaViewerPagePrivate))
#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
#define PROGRESS_DELAY 500
+#define MAX_ATTEMPTS 1024
struct _GthMediaViewerPagePrivate {
@@ -46,8 +48,14 @@ struct _GthMediaViewerPagePrivate {
GtkWidget *area;
GtkWidget *area_box;
gboolean playing;
+ gboolean paused;
+ gboolean playing_before_screenshot;
gdouble last_volume;
gint64 duration;
+ int video_fps_n;
+ int video_fps_d;
+ gboolean has_video;
+ gboolean has_audio;
gulong update_progress_id;
gdouble rate;
GtkWidget *mediabar;
@@ -75,26 +83,148 @@ static const char *media_viewer_ui_info =
"</ui>";
+typedef struct {
+ GthMediaViewerPage *self;
+ GdkPixbuf *pixbuf;
+ GthFileData *file_data;
+} SaveData;
+
+
+static void
+save_date_free (SaveData *save_data)
+{
+ _g_object_unref (save_data->file_data);
+ _g_object_unref (save_data->pixbuf);
+ g_free (save_data);
+}
+
+
+static void
+screenshot_saved_cb (GthFileData *file_data,
+ GError *error,
+ gpointer user_data)
+{
+ SaveData *save_data = user_data;
+ GthMediaViewerPage *self = save_data->self;
+
+ if (error != NULL)
+ _gtk_error_dialog_from_gerror_show (GTK_WINDOW (self->priv->browser), _("Could not save the file"), &error);
+ else if (self->priv->playing_before_screenshot)
+ gst_element_set_state (self->priv->playbin, GST_STATE_PLAYING);
+
+ save_date_free (save_data);
+}
+
+
+static void
+save_as_response_cb (GtkDialog *file_sel,
+ int response,
+ SaveData *save_data)
+{
+ GFile *file;
+ GFile *folder;
+ char *folder_uri;
+ const char *mime_type;
+
+ if (response != GTK_RESPONSE_OK) {
+ GthMediaViewerPage *self = save_data->self;
+
+ if (self->priv->playing_before_screenshot)
+ gst_element_set_state (self->priv->playbin, GST_STATE_PLAYING);
+ save_date_free (save_data);
+ gtk_widget_destroy (GTK_WIDGET (file_sel));
+ return;
+ }
+
+ if (! gth_file_chooser_dialog_get_file (GTH_FILE_CHOOSER_DIALOG (file_sel), &file, &mime_type))
+ return;
+
+ folder = g_file_get_parent (file);
+ folder_uri = g_file_get_uri (folder);
+ eel_gconf_set_string (PREF_GSTREAMER_SCREESHOT_LOCATION, folder_uri);
+
+ save_data->file_data = gth_file_data_new (file, NULL);
+ gth_file_data_set_mime_type (save_data->file_data, mime_type);
+ _gdk_pixbuf_save_async (save_data->pixbuf,
+ save_data->file_data,
+ mime_type,
+ screenshot_saved_cb,
+ save_data);
+
+ gtk_widget_destroy (GTK_WIDGET (file_sel));
+
+ g_free (folder_uri);
+ g_object_unref (folder);
+ g_object_unref (file);
+}
+
+
static void
screenshot_ready_cb (GdkPixbuf *pixbuf,
gpointer user_data)
{
GthMediaViewerPage *self = user_data;
- GtkWidget *image;
- GtkWidget *window;
+ SaveData *save_data;
+ GtkWidget *file_sel;
if (pixbuf == NULL) {
_gtk_error_dialog_from_gerror_show (GTK_WINDOW (self->priv->browser), _("Could not take a screenshot"), NULL);
return;
}
- image = gtk_image_new_from_pixbuf (pixbuf);
- gtk_widget_show (image);
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_container_add (GTK_CONTAINER (window), image);
- gtk_window_present (GTK_WINDOW (window));
+ save_data = g_new0 (SaveData, 1);
+ save_data->self = self;
+ save_data->pixbuf = pixbuf;
+
+ file_sel = gth_file_chooser_dialog_new (_("Save Image"), GTK_WINDOW (self->priv->browser), "pixbuf-saver");
- g_object_unref (pixbuf);
+ {
+ char *last_uri;
+ GFile *last_folder;
+ char *prefix;
+ char *display_name;
+ int attempt;
+
+ last_uri = eel_gconf_get_string (PREF_GSTREAMER_SCREESHOT_LOCATION, "~");
+ if ((last_uri == NULL) || (strcmp (last_uri, "~") == 0))
+ last_folder = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
+ else
+ last_folder = g_file_new_for_uri (last_uri);
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (file_sel), last_folder, NULL);
+
+ prefix = _g_utf8_remove_extension (g_file_info_get_display_name (self->priv->file_data->info));
+ if (prefix == NULL)
+ prefix = g_strdup (C_("Filename", "Screenshot"));
+ display_name = NULL;
+ for (attempt = 1; attempt < MAX_ATTEMPTS; attempt++) {
+ GFile *proposed_file;
+
+ g_free (display_name);
+
+ display_name = g_strdup_printf ("%s-%02d.jpeg", prefix, attempt);
+ proposed_file = g_file_get_child_for_display_name (last_folder, display_name, NULL);
+ if ((proposed_file != NULL) && ! g_file_query_exists (proposed_file, NULL)) {
+ g_object_unref (proposed_file);
+ break;
+ }
+ }
+
+ if (display_name != NULL) {
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_sel), display_name);
+ g_free (display_name);
+ }
+
+ g_free (prefix);
+ g_object_unref (last_folder);
+ g_free (last_uri);
+ }
+
+ g_signal_connect (GTK_DIALOG (file_sel),
+ "response",
+ G_CALLBACK (save_as_response_cb),
+ save_data);
+
+ gtk_widget_show (file_sel);
}
@@ -105,9 +235,12 @@ media_viewer_activate_action_screenshot (GtkAction *action,
if (self->priv->playbin == NULL)
return;
+ self->priv->playing_before_screenshot = self->priv->playing;
+ if (self->priv->playing)
+ gst_element_set_state (self->priv->playbin, GST_STATE_PAUSED);
_gst_playbin_get_current_frame (self->priv->playbin,
- 0 /*self->priv->video_fps_n*/,
- 0 /*self->priv->video_fps_d*/,
+ self->priv->video_fps_n,
+ self->priv->video_fps_d,
screenshot_ready_cb,
self);
}
@@ -191,22 +324,74 @@ volume_value_changed_cb (GtkAdjustment *adjustment,
}
+static void position_value_changed_cb (GtkAdjustment *adjustment,
+ gpointer user_data);
+
+
+static void
+update_current_position_bar (GthMediaViewerPage *self,
+ gboolean update_progressbar)
+{
+ GstFormat format;
+ gint64 current_value = 0;
+
+ format = GST_FORMAT_TIME;
+ if (gst_element_query_position (self->priv->playbin, &format, ¤t_value)) {
+ char *s;
+
+ if (self->priv->duration <= 0) {
+ gst_element_query_duration (self->priv->playbin, &format, &self->priv->duration);
+ s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (self->priv->duration));
+ gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_duration")), s);
+
+ g_free (s);
+ }
+
+ /*
+ g_print ("==> %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " (%0.3g)\n" ,
+ current_value,
+ self->priv->duration,
+ ((double) current_value / self->priv->duration) * 100.0);
+ */
+
+ if (update_progressbar) {
+ g_signal_handlers_block_by_func(GET_WIDGET ("adjustment_position"), position_value_changed_cb, self);
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("adjustment_position")), (self->priv->duration > 0) ? ((double) current_value / self->priv->duration) * 100.0 : 0.0);
+ g_signal_handlers_unblock_by_func(GET_WIDGET ("adjustment_position"), position_value_changed_cb, self);
+ }
+
+ s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (current_value));
+ gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_position")), s);
+
+ g_free (s);
+ }
+}
+
+
static void
position_value_changed_cb (GtkAdjustment *adjustment,
gpointer user_data)
{
GthMediaViewerPage *self = user_data;
+ gint64 current_value;
+ char *s;
if (self->priv->playbin == NULL)
return;
+ current_value = (gint64) (gtk_adjustment_get_value (adjustment) / 100.0 * self->priv->duration);
if (! gst_element_seek_simple (self->priv->playbin,
GST_FORMAT_TIME,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
- (gint64) (gtk_adjustment_get_value (adjustment) / 100.0 * self->priv->duration)))
+ current_value))
{
g_warning ("seek failed");
}
+
+ s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (current_value));
+ gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_position")), s);
+
+ g_free (s);
}
@@ -252,7 +437,15 @@ button_play_clicked_cb (GtkButton *button,
if (self->priv->playbin == NULL)
return;
- gst_element_set_state (self->priv->playbin, ! self->priv->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED);
+ if (! self->priv->playing) {
+ if (! self->priv->paused) {
+ gst_element_set_state (self->priv->playbin, GST_STATE_PAUSED);
+ gst_element_seek_simple (self->priv->playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, 0);
+ }
+ gst_element_set_state (self->priv->playbin, GST_STATE_PLAYING);
+ }
+ else
+ gst_element_set_state (self->priv->playbin, GST_STATE_PAUSED);
}
@@ -320,43 +513,6 @@ update_volume_from_playbin (GthMediaViewerPage *self)
}
-static void
-update_current_position_bar (GthMediaViewerPage *self)
-{
- GstFormat format;
- gint64 current_value = 0;
-
- format = GST_FORMAT_TIME;
- if (gst_element_query_position (self->priv->playbin, &format, ¤t_value)) {
- char *s;
-
- if (self->priv->duration <= 0) {
- gst_element_query_duration (self->priv->playbin, &format, &self->priv->duration);
- s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (self->priv->duration));
- gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_duration")), s);
-
- g_free (s);
- }
-
- /*
- g_print ("==> %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " (%0.3g)\n" ,
- current_value,
- self->priv->duration,
- ((double) current_value / self->priv->duration) * 100.0);
- */
-
- g_signal_handlers_block_by_func(GET_WIDGET ("adjustment_position"), position_value_changed_cb, self);
- gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("adjustment_position")), (self->priv->duration > 0) ? ((double) current_value / self->priv->duration) * 100.0 : 0.0);
- g_signal_handlers_unblock_by_func(GET_WIDGET ("adjustment_position"), position_value_changed_cb, self);
-
- s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (current_value));
- gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_position")), s);
-
- g_free (s);
- }
-}
-
-
static gboolean
update_progress_cb (gpointer user_data)
{
@@ -367,7 +523,7 @@ update_progress_cb (gpointer user_data)
self->priv->update_progress_id = 0;
}
- update_current_position_bar (self);
+ update_current_position_bar (self, TRUE);
self->priv->update_progress_id = gdk_threads_add_timeout (PROGRESS_DELAY, update_progress_cb, self);
@@ -549,6 +705,63 @@ reset_player_state (GthMediaViewerPage *self)
static void
+update_stream_info (GthMediaViewerPage *self)
+{
+ GList *streaminfo;
+ GstPad *videopad;
+
+ streaminfo = NULL;
+ videopad = NULL;
+
+ g_object_get (self->priv->playbin, "stream-info", &streaminfo, NULL);
+ streaminfo = g_list_copy (streaminfo);
+ g_list_foreach (streaminfo, (GFunc) g_object_ref, NULL);
+
+ for (/* void */ ; streaminfo; streaminfo = streaminfo->next) {
+ GObject *info;
+ int type;
+ GParamSpec *pspec;
+ GEnumValue *val;
+
+ info = streaminfo->data;
+ if (info == NULL)
+ continue;
+
+ type = -1;
+
+ g_object_get (info, "type", &type, NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (info), "type");
+ val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
+
+ if (strcmp (val->value_nick, "audio") == 0) {
+ self->priv->has_audio = TRUE;
+ }
+ else if (strcmp (val->value_nick, "video") == 0) {
+ self->priv->has_video = TRUE;
+ if (videopad == NULL)
+ g_object_get (info, "object", &videopad, NULL);
+ }
+ }
+
+ if (videopad != NULL) {
+ GstCaps *caps;
+
+ if ((caps = gst_pad_get_negotiated_caps (videopad)) != NULL) {
+ GstStructure *structure;
+
+ structure = gst_caps_get_structure (caps, 0);
+ gst_structure_get_fraction (structure, "framerate", &self->priv->video_fps_n, &self->priv->video_fps_d);
+
+ gst_caps_unref (caps);
+ }
+ }
+
+ g_list_foreach (streaminfo, (GFunc) g_object_unref, NULL);
+ g_list_free (streaminfo);
+}
+
+
+static void
bus_message_cb (GstBus *bus,
GstMessage *message,
gpointer user_data)
@@ -564,13 +777,19 @@ bus_message_cb (GstBus *bus,
old_state = new_state = GST_STATE_NULL;
gst_message_parse_state_changed (message, &old_state, &new_state, &pending_state);
+ self->priv->paused = (new_state == GST_STATE_PAUSED);
+
if (old_state == new_state)
break;
if (GST_MESSAGE_SRC (message) != GST_OBJECT (self->priv->playbin))
break;
- update_current_position_bar (self);
+ update_current_position_bar (self, TRUE);
+ if ((old_state == GST_STATE_READY) && (new_state == GST_STATE_PAUSED)) {
+ update_stream_info (self);
+ gth_viewer_page_update_sensitivity (GTH_VIEWER_PAGE (self));
+ }
if ((old_state == GST_STATE_READY) || (new_state == GST_STATE_PAUSED))
update_volume_from_playbin (self);
if ((old_state == GST_STATE_PLAYING) || (new_state == GST_STATE_PLAYING))
@@ -583,13 +802,12 @@ bus_message_cb (GstBus *bus,
format = GST_FORMAT_TIME;
gst_message_parse_duration (message, &format, &self->priv->duration);
- update_current_position_bar (self);
+ update_current_position_bar (self, TRUE);
break;
}
case GST_MESSAGE_EOS:
reset_player_state (self);
- /*gst_element_set_state (self->priv->playbin, GST_STATE_READY);*/
break;
case GST_MESSAGE_BUFFERING: {
@@ -635,10 +853,9 @@ gth_media_viewer_page_real_show (GthViewerPage *base)
gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
- if (self->priv->playbin != NULL) {
- gst_element_set_state (self->priv->playbin, GST_STATE_NULL);
- gst_object_unref (GST_OBJECT (self->priv->playbin));
- }
+ if (self->priv->playbin != NULL)
+ return;
+
self->priv->playbin = gst_element_factory_make ("playbin", "playbin");
g_signal_connect (self->priv->playbin, "notify::volume", G_CALLBACK (playbin_notify_volume_cb), self);
@@ -813,12 +1030,26 @@ gth_media_viewer_page_real_show_pointer (GthViewerPage *base,
static void
+set_action_sensitive (GthMediaViewerPage *self,
+ const char *action_name,
+ gboolean sensitive)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (self->priv->actions, action_name);
+ g_object_set (action, "sensitive", sensitive, NULL);
+}
+
+
+static void
gth_media_viewer_page_real_update_sensitivity (GthViewerPage *base)
{
GthMediaViewerPage *self = (GthMediaViewerPage *) base;
gtk_widget_set_sensitive (GET_WIDGET ("button_play_slower"), self->priv->playing);
gtk_widget_set_sensitive (GET_WIDGET ("button_play_faster"), self->priv->playing);
+
+ set_action_sensitive (self, "MediaViewer_Screenshot", self->priv->has_video);
}
@@ -914,6 +1145,10 @@ gth_media_viewer_page_instance_init (GthMediaViewerPage *self)
self->priv = GTH_MEDIA_VIEWER_PAGE_GET_PRIVATE (self);
self->priv->update_progress_id = 0;
self->priv->video_present = FALSE;
+ self->priv->has_video = FALSE;
+ self->priv->has_audio = FALSE;
+ self->priv->video_fps_n = 0;
+ self->priv->video_fps_d = 0;
}
diff --git a/extensions/gstreamer/preferences.h b/extensions/gstreamer/preferences.h
new file mode 100644
index 0000000..0cad7b1
--- /dev/null
+++ b/extensions/gstreamer/preferences.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PREFERENCES_H
+#define PREFERENCES_H
+
+#define PREF_GSTREAMER_SCREESHOT_LOCATION "/apps/gthumb/ext/gstreamer/screenshot_location"
+
+#endif /* PREFERENCES_H */
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 5664657..ff3b84e 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -788,20 +788,9 @@ typedef struct {
gpointer user_data;
GthFileData *file_data;
GtkWidget *file_sel;
- GtkWidget *format_chooser;
} SaveAsData;
-typedef struct {
- const char *type;
- const char *extensions;
- const char *default_ext;
-} Format;
-
-
-static GList *supported_formats = NULL;
-
-
static void
save_as_destroy_cb (GtkWidget *w,
SaveAsData *data)
@@ -816,12 +805,10 @@ save_as_response_cb (GtkDialog *file_sel,
int response,
SaveAsData *data)
{
- char *filename;
- int n_format;
- Format *format;
- GFile *file;
+ GFile *file;
+ const char *mime_type;
- if (response != GTK_RESPONSE_ACCEPT) {
+ if (response != GTK_RESPONSE_OK) {
if (data->func != NULL) {
(*data->func) ((GthViewerPage *) data->self,
data->file_data,
@@ -832,19 +819,13 @@ save_as_response_cb (GtkDialog *file_sel,
return;
}
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_sel));
- n_format = egg_file_format_chooser_get_format (EGG_FILE_FORMAT_CHOOSER (data->format_chooser), filename);
- g_free (filename);
-
- if ((n_format < 1) || (n_format > g_list_length (supported_formats)))
+ if (! gth_file_chooser_dialog_get_file (GTH_FILE_CHOOSER_DIALOG (file_sel), &file, &mime_type))
return;
- format = g_list_nth_data (supported_formats, n_format - 1);
- file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (file_sel));
gth_file_data_set_file (data->file_data, file);
_gth_image_viewer_page_real_save ((GthViewerPage *) data->self,
file,
- format->type,
+ mime_type,
data->func,
data->user_data);
gtk_widget_destroy (GTK_WIDGET (data->file_sel));
@@ -854,140 +835,29 @@ save_as_response_cb (GtkDialog *file_sel,
static void
-format_chooser_selection_changed_cb (EggFileFormatChooser *self,
- SaveAsData *data)
-{
- char *filename;
- int n_format;
- Format *format;
- char *basename;
- char *basename_noext;
- char *new_basename;
-
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (data->file_sel));
- n_format = egg_file_format_chooser_get_format (EGG_FILE_FORMAT_CHOOSER (data->format_chooser), filename);
-
- if ((n_format < 1) || (n_format > g_list_length (supported_formats))) {
- g_free (filename);
- return;
- }
-
- format = g_list_nth_data (supported_formats, n_format - 1);
- basename = g_path_get_basename (filename);
- basename_noext = _g_uri_remove_extension (basename);
- new_basename = g_strconcat (basename_noext, ".", format->default_ext, NULL);
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (data->file_sel), new_basename);
-
- g_free (new_basename);
- g_free (basename_noext);
- g_free (basename);
- g_free (filename);
-}
-
-
-static char *
-get_icon_name_for_type (const char *mime_type)
-{
- char *name = NULL;
-
- if (mime_type != NULL) {
- char *s;
-
- name = g_strconcat ("gnome-mime-", mime_type, NULL);
- for (s = name; *s; ++s)
- if (! g_ascii_isalpha (*s))
- *s = '-';
- }
-
- if ((name == NULL) || ! gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name)) {
- g_free (name);
- name = g_strdup ("image-x-generic");
- }
-
- return name;
-}
-
-
-static void
gth_image_viewer_page_real_save_as (GthViewerPage *base,
FileSavedFunc func,
gpointer user_data)
{
- GthImageViewerPage *self;
- GtkWidget *file_sel;
- char *uri;
- EggFileFormatChooser *format_chooser;
- SaveAsData *data;
- GList *scan;
+ GthImageViewerPage *self;
+ GtkWidget *file_sel;
+ char *uri;
+ SaveAsData *data;
self = GTH_IMAGE_VIEWER_PAGE (base);
- file_sel = gtk_file_chooser_dialog_new (_("Save Image"),
+ file_sel = gth_file_chooser_dialog_new (_("Save Image"),
GTK_WINDOW (self->priv->browser),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (file_sel), FALSE);
- gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (file_sel), TRUE);
- gtk_dialog_set_default_response (GTK_DIALOG (file_sel), GTK_RESPONSE_ACCEPT);
+ "pixbuf-saver");
+
uri = g_file_get_uri (self->priv->file_data->file);
gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (file_sel), uri);
- /**/
-
- if (supported_formats == NULL) {
- GArray *savers;
- int i;
-
- savers = gth_main_get_type_set ("pixbuf-saver");
- for (i = 0; (savers != NULL) && (i < savers->len); i++) {
- GthPixbufSaver *pixbuf_saver;
- Format *format;
-
- pixbuf_saver = g_object_new (g_array_index (savers, GType, i), NULL);
- format = g_new (Format, 1);
- format->type = g_strdup (gth_pixbuf_saver_get_mime_type (pixbuf_saver));
- format->extensions = g_strdup (gth_pixbuf_saver_get_extensions (pixbuf_saver));
- format->default_ext = g_strdup (gth_pixbuf_saver_get_default_ext (pixbuf_saver));
- supported_formats = g_list_prepend (supported_formats, format);
-
- g_object_unref (pixbuf_saver);
- }
- }
-
- format_chooser = (EggFileFormatChooser *) egg_file_format_chooser_new ();
- for (scan = supported_formats; scan != NULL; scan = scan->next) {
- Format *format = scan->data;
- char *icon_name;
- char **extensions;
-
- icon_name = get_icon_name_for_type (format->type);
- extensions = g_strsplit (format->extensions, " ", -1);
- egg_file_format_chooser_add_format (format_chooser,
- 0,
- g_content_type_get_description (format->type),
- icon_name,
- extensions[0],
- extensions[1],
- extensions[2],
- NULL);
-
- g_strfreev (extensions);
- g_free (icon_name);
- }
-
- gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (file_sel),
- GTK_WIDGET (format_chooser));
-
- /**/
-
data = g_new0 (SaveAsData, 1);
data->self = self;
data->func = func;
data->file_data = gth_file_data_dup (self->priv->file_data);
data->user_data = user_data;
data->file_sel = file_sel;
- data->format_chooser = (GtkWidget *) format_chooser;
g_signal_connect (GTK_DIALOG (file_sel),
"response",
@@ -997,10 +867,6 @@ gth_image_viewer_page_real_save_as (GthViewerPage *base,
"destroy",
G_CALLBACK (save_as_destroy_cb),
data);
- g_signal_connect (G_OBJECT (format_chooser),
- "selection-changed",
- G_CALLBACK (format_chooser_selection_changed_cb),
- data);
gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (self->priv->browser));
gtk_window_set_modal (GTK_WINDOW (file_sel), TRUE);
diff --git a/extensions/image_viewer/preferences.h b/extensions/image_viewer/preferences.h
index 50c976f..c9d878d 100644
--- a/extensions/image_viewer/preferences.h
+++ b/extensions/image_viewer/preferences.h
@@ -37,4 +37,4 @@ void image_viewer__dlg_preferences_construct_cb (GtkWidget *dialog,
GthBrowser *browser,
GtkBuilder *builder);
-#endif /* CALLBACKS_H */
+#endif /* PREFERENCES_H */
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 388a701..9987074 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -40,6 +40,7 @@ PUBLIC_HEADER_FILES = \
gth-embedded-dialog.h \
gth-empty-list.h \
gth-extensions.h \
+ gth-file-chooser-dialog.h \
gth-error.h \
gth-file-data.h \
gth-file-list.h \
@@ -153,6 +154,7 @@ gthumb_SOURCES = \
gth-empty-list.c \
gth-error.c \
gth-extensions.c \
+ gth-file-chooser-dialog.c \
gth-file-data.c \
gth-file-list.c \
gth-file-properties.c \
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index 5d25efc..6b19b66 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -887,6 +887,25 @@ _g_utf8_all_spaces (const char *utf8_string)
}
+char *
+_g_utf8_remove_extension (const char *str)
+{
+ char *p;
+ char *ext;
+ char *dest;
+
+ if ((str == NULL) || ! g_utf8_validate (str, -1, NULL))
+ return NULL;
+
+ p = (char *) str;
+ ext = g_utf8_strrchr (p, -1, g_utf8_get_char ("."));
+ dest = g_strdup (p);
+ g_utf8_strncpy (dest, p, g_utf8_strlen (p, -1) - g_utf8_strlen (ext, -1));
+
+ return dest;
+}
+
+
GList *
_g_list_insert_list_before (GList *list1,
GList *sibling,
@@ -926,6 +945,7 @@ _g_list_insert_list_before (GList *list1,
GHashTable *static_strings = NULL;
+static GStaticMutex static_strings_mutex = G_STATIC_MUTEX_INIT;
const char *
@@ -936,6 +956,8 @@ get_static_string (const char *s)
if (s == NULL)
return NULL;
+ g_static_mutex_lock (&static_strings_mutex);
+
if (static_strings == NULL)
static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -946,6 +968,8 @@ get_static_string (const char *s)
GINT_TO_POINTER (1));
}
+ g_static_mutex_unlock (&static_strings_mutex);
+
return result;
}
diff --git a/gthumb/glib-utils.h b/gthumb/glib-utils.h
index d79a6e5..f0ed738 100644
--- a/gthumb/glib-utils.h
+++ b/gthumb/glib-utils.h
@@ -166,6 +166,7 @@ char ** _g_utf8_strsplit (const char *string,
int max_tokens);
char * _g_utf8_strstrip (const char *str);
gboolean _g_utf8_all_spaces (const char *utf8_string);
+char * _g_utf8_remove_extension (const char *str);
GList * _g_list_insert_list_before (GList *list1,
GList *sibling,
GList *list2);
diff --git a/gthumb/gth-file-chooser-dialog.c b/gthumb/gth-file-chooser-dialog.c
new file mode 100644
index 0000000..159c65a
--- /dev/null
+++ b/gthumb/gth-file-chooser-dialog.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 The Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include "eggfileformatchooser.h"
+#include "glib-utils.h"
+#include "gth-file-chooser-dialog.h"
+#include "gth-main.h"
+
+
+typedef struct {
+ const char *type;
+ const char *extensions;
+ const char *default_ext;
+} Format;
+
+
+static gpointer parent_class = NULL;
+
+
+struct _GthFileChooserDialogPrivate {
+ GList *supported_formats;
+ EggFileFormatChooser *format_chooser;
+};
+
+
+static void
+gth_file_chooser_dialog_finalize (GObject *object)
+{
+ GthFileChooserDialog *self;
+
+ self = GTH_FILE_CHOOSER_DIALOG (object);
+
+ g_list_foreach (self->priv->supported_formats, (GFunc) g_free, NULL);
+ g_list_free (self->priv->supported_formats);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gth_file_chooser_dialog_class_init (GthFileChooserDialogClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (GthFileChooserDialogPrivate));
+
+ object_class = (GObjectClass*) class;
+ object_class->finalize = gth_file_chooser_dialog_finalize;
+}
+
+
+static void
+gth_file_chooser_dialog_init (GthFileChooserDialog *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_FILE_CHOOSER_DIALOG, GthFileChooserDialogPrivate);
+ self->priv->supported_formats = NULL;
+}
+
+
+GType
+gth_file_chooser_dialog_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type) {
+ GTypeInfo type_info = {
+ sizeof (GthFileChooserDialogClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gth_file_chooser_dialog_class_init,
+ NULL,
+ NULL,
+ sizeof (GthFileChooserDialog),
+ 0,
+ (GInstanceInitFunc) gth_file_chooser_dialog_init
+ };
+
+ type = g_type_register_static (GTK_TYPE_FILE_CHOOSER_DIALOG,
+ "GthFileChooserDialog",
+ &type_info,
+ 0);
+ }
+
+ return type;
+}
+
+
+static void
+format_chooser_selection_changed_cb (EggFileFormatChooser *format_chooser,
+ GthFileChooserDialog *self)
+{
+ char *filename;
+ int n_format;
+ Format *format;
+ char *basename;
+ char *basename_noext;
+ char *new_basename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (self));
+ if (filename == NULL)
+ return;
+
+ n_format = egg_file_format_chooser_get_format (EGG_FILE_FORMAT_CHOOSER (self->priv->format_chooser), filename);
+
+ if ((n_format < 1) || (n_format > g_list_length (self->priv->supported_formats))) {
+ g_free (filename);
+ return;
+ }
+
+ format = g_list_nth_data (self->priv->supported_formats, n_format - 1);
+ basename = g_path_get_basename (filename);
+ basename_noext = _g_uri_remove_extension (basename);
+ new_basename = g_strconcat (basename_noext, ".", format->default_ext, NULL);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (self), new_basename);
+
+ g_free (new_basename);
+ g_free (basename_noext);
+ g_free (basename);
+ g_free (filename);
+}
+
+
+static char *
+get_icon_name_for_type (const char *mime_type)
+{
+ char *name = NULL;
+
+ if (mime_type != NULL) {
+ char *s;
+
+ name = g_strconcat ("gnome-mime-", mime_type, NULL);
+ for (s = name; *s; ++s)
+ if (! g_ascii_isalpha (*s))
+ *s = '-';
+ }
+
+ if ((name == NULL) || ! gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name)) {
+ g_free (name);
+ name = g_strdup ("image-x-generic");
+ }
+
+ return name;
+}
+
+
+static void
+gth_file_chooser_dialog_construct (GthFileChooserDialog *self,
+ const char *title,
+ GtkWindow *parent,
+ const char *allowed_savers)
+{
+ GArray *savers;
+ int i;
+ GList *scan;
+
+ if (title != NULL)
+ gtk_window_set_title (GTK_WINDOW (self), title);
+ if (parent != NULL)
+ gtk_window_set_transient_for (GTK_WINDOW (self), parent);
+
+ gtk_file_chooser_set_action (GTK_FILE_CHOOSER (self), GTK_FILE_CHOOSER_ACTION_SAVE);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (self), FALSE);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (self), TRUE);
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
+
+ gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_SAVE, GTK_RESPONSE_OK);
+
+ /**/
+
+ savers = gth_main_get_type_set (allowed_savers /*"pixbuf-saver"*/);
+ for (i = 0; (savers != NULL) && (i < savers->len); i++) {
+ GthPixbufSaver *saver;
+ Format *format;
+
+ saver = g_object_new (g_array_index (savers, GType, i), NULL);
+ format = g_new (Format, 1);
+ format->type = get_static_string (gth_pixbuf_saver_get_mime_type (saver));
+ format->extensions = get_static_string (gth_pixbuf_saver_get_extensions (saver));
+ format->default_ext = get_static_string (gth_pixbuf_saver_get_default_ext (saver));
+ self->priv->supported_formats = g_list_prepend (self->priv->supported_formats, format);
+
+ g_object_unref (saver);
+ }
+
+ self->priv->format_chooser = (EggFileFormatChooser *) egg_file_format_chooser_new ();
+ for (scan = self->priv->supported_formats; scan != NULL; scan = scan->next) {
+ Format *format = scan->data;
+ char *icon_name;
+ char **extensions;
+
+ icon_name = get_icon_name_for_type (format->type);
+ extensions = g_strsplit (format->extensions, " ", -1);
+ egg_file_format_chooser_add_format (self->priv->format_chooser,
+ 0,
+ g_content_type_get_description (format->type),
+ icon_name,
+ extensions[0],
+ extensions[1],
+ extensions[2],
+ NULL);
+
+ g_strfreev (extensions);
+ g_free (icon_name);
+ }
+
+ gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (self), GTK_WIDGET (self->priv->format_chooser));
+
+ g_signal_connect (G_OBJECT (self->priv->format_chooser),
+ "selection-changed",
+ G_CALLBACK (format_chooser_selection_changed_cb),
+ self);
+}
+
+
+GtkWidget *
+gth_file_chooser_dialog_new (const char *title,
+ GtkWindow *parent,
+ const char *allowed_savers)
+{
+ GthFileChooserDialog *self;
+
+ self = g_object_new (GTH_TYPE_FILE_CHOOSER_DIALOG, NULL);
+ gth_file_chooser_dialog_construct (self, title, parent, allowed_savers);
+
+ return (GtkWidget *) self;
+}
+
+
+gboolean
+gth_file_chooser_dialog_get_file (GthFileChooserDialog *self,
+ GFile **file,
+ const char **mime_type)
+{
+ char *filename;
+ int n_format;
+ Format *format;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (self));
+ n_format = egg_file_format_chooser_get_format (EGG_FILE_FORMAT_CHOOSER (self->priv->format_chooser), filename);
+ g_free (filename);
+
+ if ((n_format < 1) || (n_format > g_list_length (self->priv->supported_formats)))
+ return FALSE;
+
+ format = g_list_nth_data (self->priv->supported_formats, n_format - 1);
+ if (file != NULL)
+ *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (self));
+ if (mime_type != NULL)
+ *mime_type = format->type;
+
+ return TRUE;
+}
diff --git a/gthumb/gth-file-chooser-dialog.h b/gthumb/gth-file-chooser-dialog.h
new file mode 100644
index 0000000..8a2e971
--- /dev/null
+++ b/gthumb/gth-file-chooser-dialog.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_FILE_CHOOSER_DIALOG_H
+#define GTH_FILE_CHOOSER_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_FILE_CHOOSER_DIALOG (gth_file_chooser_dialog_get_type ())
+#define GTH_FILE_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTH_TYPE_FILE_CHOOSER_DIALOG, GthFileChooserDialog))
+#define GTH_FILE_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTH_TYPE_FILE_CHOOSER_DIALOG, GthFileChooserDialogClass))
+#define GTH_IS_FILE_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTH_TYPE_FILE_CHOOSER_DIALOG))
+#define GTH_IS_FILE_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTH_TYPE_FILE_CHOOSER_DIALOG))
+#define GTH_FILE_CHOOSER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GTH_TYPE_FILE_CHOOSER_DIALOG, GthFileChooserDialogClass))
+
+typedef struct _GthFileChooserDialog GthFileChooserDialog;
+typedef struct _GthFileChooserDialogPrivate GthFileChooserDialogPrivate;
+typedef struct _GthFileChooserDialogClass GthFileChooserDialogClass;
+
+struct _GthFileChooserDialog {
+ GtkFileChooserDialog __parent;
+ GthFileChooserDialogPrivate *priv;
+};
+
+struct _GthFileChooserDialogClass {
+ GtkFileChooserDialogClass __parent_class;
+};
+
+GType gth_file_chooser_dialog_get_type (void) G_GNUC_CONST;
+GtkWidget * gth_file_chooser_dialog_new (const char *title,
+ GtkWindow *parent,
+ const char *allowed_savers);
+gboolean gth_file_chooser_dialog_get_file (GthFileChooserDialog *self,
+ GFile **file,
+ const char **mime_type);
+
+G_END_DECLS
+
+#endif /* GTH_FILE_CHOOSER_DIALOG_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]