diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 15:59:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 15:59:36 +0000 |
commit | ec52555862913a23417735f9f7f5402f5230da13 (patch) | |
tree | 5e43a30d289a3daa69dddfbb060216ff6332f197 /extensions | |
parent | Initial commit. (diff) | |
download | nautilus-upstream.tar.xz nautilus-upstream.zip |
Adding upstream version 3.38.2.upstream/3.38.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'extensions')
23 files changed, 3182 insertions, 0 deletions
diff --git a/extensions/audio-video-properties/bacon-video-widget-properties.c b/extensions/audio-video-properties/bacon-video-widget-properties.c new file mode 100644 index 0000000..b2b2aaf --- /dev/null +++ b/extensions/audio-video-properties/bacon-video-widget-properties.c @@ -0,0 +1,283 @@ +/* bacon-video-widget-properties.c + + Copyright (C) 2002 Bastien Nocera + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. + + Author: Bastien Nocera <hadess@hadess.net> + */ + +#include "config.h" + +#include <gtk/gtk.h> +#include <glib/gi18n-lib.h> +#include <string.h> +#include <math.h> + +#include "bacon-video-widget-properties.h" + +static void bacon_video_widget_properties_dispose (GObject *object); + +struct BaconVideoWidgetPropertiesPrivate { + GtkBuilder *xml; + int time; +}; + +#define BACON_VIDEO_WIDGET_PROPERTIES_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), BACON_TYPE_VIDEO_WIDGET_PROPERTIES, BaconVideoWidgetPropertiesPrivate)) + +G_DEFINE_TYPE (BaconVideoWidgetProperties, bacon_video_widget_properties, GTK_TYPE_BOX) + +static void +bacon_video_widget_properties_class_init (BaconVideoWidgetPropertiesClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (BaconVideoWidgetPropertiesPrivate)); + + object_class->dispose = bacon_video_widget_properties_dispose; +} + +static void +bacon_video_widget_properties_init (BaconVideoWidgetProperties *props) +{ + props->priv = G_TYPE_INSTANCE_GET_PRIVATE (props, BACON_TYPE_VIDEO_WIDGET_PROPERTIES, BaconVideoWidgetPropertiesPrivate); + + gtk_orientable_set_orientation (GTK_ORIENTABLE (props), GTK_ORIENTATION_VERTICAL); +} + +static void +bacon_video_widget_properties_dispose (GObject *object) +{ + BaconVideoWidgetPropertiesPrivate *priv = BACON_VIDEO_WIDGET_PROPERTIES_GET_PRIVATE (object); + + if (priv->xml != NULL) + g_object_unref (priv->xml); + priv->xml = NULL; + + G_OBJECT_CLASS (bacon_video_widget_properties_parent_class)->dispose (object); +} + +void +bacon_video_widget_properties_set_label (BaconVideoWidgetProperties *props, + const char *name, + const char *text) +{ + GtkLabel *item; + + g_return_if_fail (props != NULL); + g_return_if_fail (BACON_IS_VIDEO_WIDGET_PROPERTIES (props)); + g_return_if_fail (name != NULL); + + item = GTK_LABEL (gtk_builder_get_object (props->priv->xml, name)); + g_return_if_fail (item != NULL); + gtk_label_set_text (item, text); +} + +void +bacon_video_widget_properties_reset (BaconVideoWidgetProperties *props) +{ + GtkWidget *item; + + g_return_if_fail (props != NULL); + g_return_if_fail (BACON_IS_VIDEO_WIDGET_PROPERTIES (props)); + + item = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "video_vbox")); + gtk_widget_show (item); + item = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "video")); + gtk_widget_set_sensitive (item, FALSE); + item = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "audio")); + gtk_widget_set_sensitive (item, FALSE); + + /* Title */ + bacon_video_widget_properties_set_label (props, "title", C_("Title", "Unknown")); + /* Artist */ + bacon_video_widget_properties_set_label (props, "artist", C_("Artist", "Unknown")); + /* Album */ + bacon_video_widget_properties_set_label (props, "album", C_("Album", "Unknown")); + /* Year */ + bacon_video_widget_properties_set_label (props, "year", C_("Year", "Unknown")); + /* Duration */ + bacon_video_widget_properties_set_duration (props, 0); + /* Comment */ + bacon_video_widget_properties_set_label (props, "comment", ""); + /* Container */ + bacon_video_widget_properties_set_label (props, "container", C_("Media container", "Unknown")); + + /* Dimensions */ + bacon_video_widget_properties_set_label (props, "dimensions", C_("Dimensions", "N/A")); + /* Video Codec */ + bacon_video_widget_properties_set_label (props, "vcodec", C_("Video codec", "N/A")); + /* Video Bitrate */ + bacon_video_widget_properties_set_label (props, "video_bitrate", + C_("Video bit rate", "N/A")); + /* Framerate */ + bacon_video_widget_properties_set_label (props, "framerate", + C_("Frame rate", "N/A")); + + /* Audio Bitrate */ + bacon_video_widget_properties_set_label (props, "audio_bitrate", + C_("Audio bit rate", "N/A")); + /* Audio Codec */ + bacon_video_widget_properties_set_label (props, "acodec", C_("Audio codec", "N/A")); + /* Sample rate */ + bacon_video_widget_properties_set_label (props, "samplerate", _("0 Hz")); + /* Channels */ + bacon_video_widget_properties_set_label (props, "channels", _("0 Channels")); +} + +static char * +time_to_string_text (gint64 msecs) +{ + char *secs, *mins, *hours, *string; + int sec, min, hour, _time; + + _time = (int) (msecs / 1000); + sec = _time % 60; + _time = _time - sec; + min = (_time % (60*60)) / 60; + _time = _time - (min * 60); + hour = _time / (60*60); + + hours = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d hour", "%d hours", hour), hour); + + mins = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d minute", + "%d minutes", min), min); + + secs = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d second", + "%d seconds", sec), sec); + + if (hour > 0) + { + /* 5 hours 2 minutes 12 seconds */ + string = g_strdup_printf (C_("time", "%s %s %s"), hours, mins, secs); + } else if (min > 0) { + /* 2 minutes 12 seconds */ + string = g_strdup_printf (C_("time", "%s %s"), mins, secs); + } else if (sec > 0) { + /* 10 seconds */ + string = g_strdup (secs); + } else { + /* 0 seconds */ + string = g_strdup (_("0 seconds")); + } + + g_free (hours); + g_free (mins); + g_free (secs); + + return string; +} + +void +bacon_video_widget_properties_set_duration (BaconVideoWidgetProperties *props, + int _time) +{ + char *string; + + g_return_if_fail (props != NULL); + g_return_if_fail (BACON_IS_VIDEO_WIDGET_PROPERTIES (props)); + + if (_time == props->priv->time) + return; + + string = time_to_string_text (_time); + bacon_video_widget_properties_set_label (props, "duration", string); + g_free (string); + + props->priv->time = _time; +} + +void +bacon_video_widget_properties_set_has_type (BaconVideoWidgetProperties *props, + gboolean has_video, + gboolean has_audio) +{ + GtkWidget *item; + + g_return_if_fail (props != NULL); + g_return_if_fail (BACON_IS_VIDEO_WIDGET_PROPERTIES (props)); + + /* Video */ + item = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "video")); + gtk_widget_set_sensitive (item, has_video); + item = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "video_vbox")); + gtk_widget_set_visible (item, has_video); + + /* Audio */ + item = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "audio")); + gtk_widget_set_sensitive (item, has_audio); +} + +void +bacon_video_widget_properties_set_framerate (BaconVideoWidgetProperties *props, + float framerate) +{ + gchar *temp; + + g_return_if_fail (props != NULL); + g_return_if_fail (BACON_IS_VIDEO_WIDGET_PROPERTIES (props)); + + if (framerate > 1.0) { + temp = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%0.2f frame per second", "%0.2f frames per second", (int) (ceilf (framerate))), framerate); + } else { + temp = g_strdup (C_("Frame rate", "N/A")); + } + bacon_video_widget_properties_set_label (props, "framerate", temp); + g_free (temp); +} + +GtkWidget* +bacon_video_widget_properties_new (void) +{ + BaconVideoWidgetProperties *props; + GtkBuilder *xml; + GtkWidget *vbox; + GtkSizeGroup *group; + const char *labels[] = { "title_label", "artist_label", "album_label", + "year_label", "duration_label", "comment_label", "container_label", + "dimensions_label", "vcodec_label", "framerate_label", + "vbitrate_label", "abitrate_label", "acodec_label", + "samplerate_label", "channels_label" }; + guint i; + + xml = gtk_builder_new (); + gtk_builder_set_translation_domain (xml, GETTEXT_PACKAGE); + if (gtk_builder_add_from_resource (xml, "/org/gnome/nautilus/audio-video-properties/ui/properties.ui", NULL) == 0) { + g_object_unref (xml); + return NULL; + } + + props = BACON_VIDEO_WIDGET_PROPERTIES (g_object_new + (BACON_TYPE_VIDEO_WIDGET_PROPERTIES, NULL)); + + props->priv->xml = xml; + vbox = GTK_WIDGET (gtk_builder_get_object (props->priv->xml, "vbox1")); + gtk_box_pack_start (GTK_BOX (props), vbox, FALSE, FALSE, 0); + + bacon_video_widget_properties_reset (props); + + group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + for (i = 0; i < G_N_ELEMENTS (labels); i++) + gtk_size_group_add_widget (group, GTK_WIDGET (gtk_builder_get_object (xml, labels[i]))); + + g_object_unref (group); + + gtk_widget_show_all (GTK_WIDGET (props)); + + return GTK_WIDGET (props); +} + diff --git a/extensions/audio-video-properties/bacon-video-widget-properties.h b/extensions/audio-video-properties/bacon-video-widget-properties.h new file mode 100644 index 0000000..32ec5e0 --- /dev/null +++ b/extensions/audio-video-properties/bacon-video-widget-properties.h @@ -0,0 +1,62 @@ +/* bacon-video-widget-properties.h: Properties dialog for BaconVideoWidget + + Copyright (C) 2002 Bastien Nocera <hadess@hadess.net> + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. + + Author: Bastien Nocera <hadess@hadess.net> + */ + +#ifndef BACON_VIDEO_WIDGET_PROPERTIES_H +#define BACON_VIDEO_WIDGET_PROPERTIES_H + +#include <gtk/gtk.h> + +#define BACON_TYPE_VIDEO_WIDGET_PROPERTIES (bacon_video_widget_properties_get_type ()) +#define BACON_VIDEO_WIDGET_PROPERTIES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BACON_TYPE_VIDEO_WIDGET_PROPERTIES, BaconVideoWidgetProperties)) +#define BACON_VIDEO_WIDGET_PROPERTIES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BACON_TYPE_VIDEO_WIDGET_PROPERTIES, BaconVideoWidgetPropertiesClass)) +#define BACON_IS_VIDEO_WIDGET_PROPERTIES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BACON_TYPE_VIDEO_WIDGET_PROPERTIES)) +#define BACON_IS_VIDEO_WIDGET_PROPERTIES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BACON_TYPE_VIDEO_WIDGET_PROPERTIES)) + +typedef struct BaconVideoWidgetProperties BaconVideoWidgetProperties; +typedef struct BaconVideoWidgetPropertiesClass BaconVideoWidgetPropertiesClass; +typedef struct BaconVideoWidgetPropertiesPrivate BaconVideoWidgetPropertiesPrivate; + +struct BaconVideoWidgetProperties { + GtkBox parent; + BaconVideoWidgetPropertiesPrivate *priv; +}; + +struct BaconVideoWidgetPropertiesClass { + GtkBoxClass parent_class; +}; + +GType bacon_video_widget_properties_get_type (void); +GtkWidget *bacon_video_widget_properties_new (void); + +void bacon_video_widget_properties_reset (BaconVideoWidgetProperties *props); +void bacon_video_widget_properties_set_label (BaconVideoWidgetProperties *props, + const char *name, + const char *text); +void bacon_video_widget_properties_set_duration (BaconVideoWidgetProperties *props, + int duration); +void bacon_video_widget_properties_set_has_type (BaconVideoWidgetProperties *props, + gboolean has_video, + gboolean has_audio); +void bacon_video_widget_properties_set_framerate (BaconVideoWidgetProperties *props, + float framerate); + +#endif /* BACON_VIDEO_WIDGET_PROPERTIES_H */ diff --git a/extensions/audio-video-properties/meson.build b/extensions/audio-video-properties/meson.build new file mode 100644 index 0000000..b67de9d --- /dev/null +++ b/extensions/audio-video-properties/meson.build @@ -0,0 +1,53 @@ +resources = gnome.compile_resources( + 'nautilus-audio-video-properties-resources', + join_paths( + 'resources', 'nautilus-audio-video-properties.gresource.xml' + ), + source_dir: 'resources', + c_name: 'nautilus_audio_video_properties', +) + +libm = cc.find_library('m') + +libtotem_properties_page_sources = files( + 'totem-properties-main.c', + 'totem-properties-view.c', + 'bacon-video-widget-properties.c', + 'totem-gst-helpers.c', +) + resources + +libtotem_properties_page_deps = [ + libm, + gst_tag_dep, + gst_pbutils_dep, +] + +libtotem_properties_page = shared_module( + 'totem-properties-page', + sources: libtotem_properties_page_sources, + dependencies: libtotem_properties_page_deps + [ + nautilus_extension + ], + c_args: [ + '-DG_LOG_DOMAIN="TotemPropertiesPage"' + ], + install: true, + install_dir: extensiondir +) + +test_properties_page_sources = files( + 'totem-properties-main.c', + 'totem-properties-view.c', + 'bacon-video-widget-properties.c', + 'totem-gst-helpers.c', + 'test-properties-page.c' +) + resources + +executable( + 'test-properties-page', + test_properties_page_sources, + dependencies: libtotem_properties_page_deps + [ + nautilus_extension + ], +) + diff --git a/extensions/audio-video-properties/resources/nautilus-audio-video-properties.gresource.xml b/extensions/audio-video-properties/resources/nautilus-audio-video-properties.gresource.xml new file mode 100644 index 0000000..d7f727d --- /dev/null +++ b/extensions/audio-video-properties/resources/nautilus-audio-video-properties.gresource.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/org/gnome/nautilus/audio-video-properties"> + <file compressed="true">ui/properties.ui</file> + </gresource> +</gresources> diff --git a/extensions/audio-video-properties/resources/ui/properties.ui b/extensions/audio-video-properties/resources/ui/properties.ui new file mode 100644 index 0000000..e7bbf88 --- /dev/null +++ b/extensions/audio-video-properties/resources/ui/properties.ui @@ -0,0 +1,692 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.20.0 --> +<interface> + <requires lib="gtk+" version="3.11"/> + <object class="GtkBox" id="vbox1"> + <property name="width_request">375</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">12</property> + <property name="border_width">6</property> + <property name="orientation">vertical</property> + <property name="spacing">18</property> + <child> + <object class="GtkBox" id="general_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="bvwp_general_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">General</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="general"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="title_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Title:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="title"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="artist_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Artist:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="artist"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="duration_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Duration:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="duration"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="year_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Year:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="year"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="album_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Album:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="album"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="title"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">Unknown</property> + <property name="wrap">True</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="title_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="artist"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">Unknown</property> + <property name="wrap">True</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="artist_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="album"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">Unknown</property> + <property name="wrap">True</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="album_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="year"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">Unknown</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="year_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="duration"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 seconds</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="duration_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="comment_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Comment:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="comment"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">5</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="comment"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">Unknown</property> + <property name="wrap">True</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="comment_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">5</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="container_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Container:</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">6</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="container"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label">Unknown</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">6</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="video_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="bvwp_video_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Video</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="video"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="dimensions_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Dimensions:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="dimensions"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="vcodec_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Codec:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="vcodec"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="framerate_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Frame rate:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="framerate"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="vbitrate_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Bit rate:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="video_bitrate"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="dimensions"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 x 0</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="dimensions_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="vcodec"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">N/A</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="vcodec_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="framerate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 frames per second</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="framerate_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="video_bitrate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 kbps</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="vbitrate_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="audio_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="bvwp_audio_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Audio</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="audio"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="samplerate_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Sample rate:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="samplerate"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="samplerate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 Hz</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="samplerate_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="abitrate_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Bit rate:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="audio_bitrate"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_bitrate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 kbps</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="abitrate_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="acodec_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Codec:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="acodec"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="acodec"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">N/A</property> + <property name="selectable">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="acodec_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="channels_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="label" translatable="yes">Channels:</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <attributes> + <attribute name="style" value="italic"/> + </attributes> + <accessibility> + <relation type="label-for" target="channels"/> + </accessibility> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="channels"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">0 Channels</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <accessibility> + <relation type="labelled-by" target="channels_label"/> + </accessibility> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> +</interface> diff --git a/extensions/audio-video-properties/test-properties-page.c b/extensions/audio-video-properties/test-properties-page.c new file mode 100644 index 0000000..21be43a --- /dev/null +++ b/extensions/audio-video-properties/test-properties-page.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005 Bastien Nocera <hadess@hadess.net> + * + * This library 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 library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <config.h> +#include <string.h> +#define GST_USE_UNSTABLE_API 1 +#include <gst/gst.h> +#include <glib/gi18n-lib.h> +#include "totem-gst-helpers.h" +#include "totem-properties-view.h" + +static GtkWidget *window, *props, *label; + +static void +create_props (const char *url) +{ + label = gtk_label_new ("Audio/Video"); + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (gtk_main_quit), NULL); + gtk_window_set_default_size (GTK_WINDOW (window), 450, 550); + props = totem_properties_view_new (url, label); + gtk_container_add (GTK_CONTAINER (window), props); + + gtk_widget_show_all (window); +} + +static void +destroy_props (void) +{ + gtk_widget_destroy (label); +} + +int main (int argc, char **argv) +{ + GFile *file; + char *url; + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + totem_gst_disable_display_decoders (); + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + if (argc != 2) { + g_print ("Usage: %s [URI]\n", argv[0]); + return 1; + } + + file = g_file_new_for_commandline_arg (argv[1]); + url = g_file_get_uri (file); + g_object_unref (file); + + create_props (url); + g_free (url); + + gtk_main (); + + destroy_props (); + + return 0; +} + diff --git a/extensions/audio-video-properties/totem-gst-helpers.c b/extensions/audio-video-properties/totem-gst-helpers.c new file mode 100644 index 0000000..e01996d --- /dev/null +++ b/extensions/audio-video-properties/totem-gst-helpers.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2003-2007 the GStreamer project + * Julien Moutte <julien@moutte.net> + * Ronald Bultje <rbultje@ronald.bitfreak.net> + * Copyright (C) 2005-2008 Tim-Philipp Müller <tim centricular net> + * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * Copyright © 2009 Christian Persch + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "totem-gst-helpers.h" +#include <gst/gstprotection.h> + +/* Disable decoders that require a display environment to work, + * and that might cause crashes */ +void +totem_gst_disable_display_decoders (void) +{ + GstRegistry *registry; + const char *blacklisted_plugins[] = { + "bmcdec", + "vaapi", + "video4linux2" + }; + guint i; + + /* Disable the vaapi plugin as it will not work with the + * fakesink we use: + * See: https://bugzilla.gnome.org/show_bug.cgi?id=700186 and + * https://bugzilla.gnome.org/show_bug.cgi?id=749605 */ + registry = gst_registry_get (); + + for (i = 0; i < G_N_ELEMENTS (blacklisted_plugins); i++) { + GstPlugin *plugin = + gst_registry_find_plugin (registry, + blacklisted_plugins[i]); + if (plugin) + gst_registry_remove_plugin (registry, plugin); + } +} + +/* + * vim: sw=2 ts=8 cindent noai bs=2 + */ diff --git a/extensions/audio-video-properties/totem-gst-helpers.h b/extensions/audio-video-properties/totem-gst-helpers.h new file mode 100644 index 0000000..9ec559c --- /dev/null +++ b/extensions/audio-video-properties/totem-gst-helpers.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2001,2002,2003,2004,2005 Bastien Nocera <hadess@hadess.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef HAVE_TOTEM_GST_HELPERS_H +#define HAVE_TOTEM_GST_HELPERS_H + +void totem_gst_disable_display_decoders (void); + +#endif /* HAVE_TOTEM_GST_HELPERS_H */ diff --git a/extensions/audio-video-properties/totem-mime-types.h b/extensions/audio-video-properties/totem-mime-types.h new file mode 100644 index 0000000..6551f31 --- /dev/null +++ b/extensions/audio-video-properties/totem-mime-types.h @@ -0,0 +1,282 @@ +/* generated with mime-types-include.sh, don't edit */ +G_GNUC_UNUSED static const gchar *mime_types[] = { +"application/mxf", +"application/ogg", +"application/ram", +"application/sdp", +"application/smil", +"application/smil+xml", +"application/vnd.apple.mpegurl", +"application/vnd.ms-asf", +"application/vnd.ms-wpl", +"application/vnd.rn-realmedia", +"application/vnd.rn-realmedia-vbr", +"application/x-extension-m4a", +"application/x-extension-mp4", +"application/x-flac", +"application/x-flash-video", +"application/x-matroska", +"application/x-netshow-channel", +"application/x-ogg", +"application/x-quicktime-media-link", +"application/x-quicktimeplayer", +"application/x-shorten", +"application/x-smil", +"application/xspf+xml", +"audio/3gpp", +"audio/3gpp2", +"audio/aac", +"audio/ac3", +"audio/AMR", +"audio/AMR-WB", +"audio/basic", +"audio/dv", +"audio/eac3", +"audio/flac", +"audio/m4a", +"audio/midi", +"audio/mp1", +"audio/mp2", +"audio/mp3", +"audio/mp4", +"audio/mpeg", +"audio/mpegurl", +"audio/mpg", +"audio/ogg", +"audio/opus", +"audio/prs.sid", +"audio/scpls", +"audio/vnd.rn-realaudio", +"audio/wav", +"audio/webm", +"audio/x-aac", +"audio/x-aiff", +"audio/x-ape", +"audio/x-flac", +"audio/x-gsm", +"audio/x-it", +"audio/x-m4a", +"audio/x-m4b", +"audio/x-matroska", +"audio/x-mod", +"audio/x-mp1", +"audio/x-mp2", +"audio/x-mp3", +"audio/x-mpg", +"audio/x-mpeg", +"audio/x-mpegurl", +"audio/x-ms-asf", +"audio/x-ms-asx", +"audio/x-ms-wax", +"audio/x-ms-wma", +"audio/x-musepack", +"audio/x-opus+ogg", +"audio/x-pn-aiff", +"audio/x-pn-au", +"audio/x-pn-realaudio", +"audio/x-pn-realaudio-plugin", +"audio/x-pn-wav", +"audio/x-pn-windows-acm", +"audio/x-realaudio", +"audio/x-real-audio", +"audio/x-s3m", +"audio/x-sbc", +"audio/x-scpls", +"audio/x-shorten", +"audio/x-speex", +"audio/x-stm", +"audio/x-tta", +"audio/x-wav", +"audio/x-wavpack", +"audio/x-vorbis", +"audio/x-vorbis+ogg", +"audio/x-xm", +"image/vnd.rn-realpix", +"image/x-pict", +"misc/ultravox", +"text/google-video-pointer", +"text/x-google-video-pointer", +"video/3gp", +"video/3gpp", +"video/3gpp2", +"video/dv", +"video/divx", +"video/fli", +"video/flv", +"video/mp2t", +"video/mp4", +"video/mp4v-es", +"video/mpeg", +"video/mpeg-system", +"video/msvideo", +"video/ogg", +"video/quicktime", +"video/vivo", +"video/vnd.divx", +"video/vnd.mpegurl", +"video/vnd.rn-realvideo", +"video/vnd.vivo", +"video/webm", +"video/x-anim", +"video/x-avi", +"video/x-flc", +"video/x-fli", +"video/x-flic", +"video/x-flv", +"video/x-m4v", +"video/x-matroska", +"video/x-mjpeg", +"video/x-mpeg", +"video/x-mpeg2", +"video/x-ms-asf", +"video/x-ms-asf-plugin", +"video/x-ms-asx", +"video/x-msvideo", +"video/x-ms-wm", +"video/x-ms-wmv", +"video/x-ms-wmx", +"video/x-ms-wvx", +"video/x-nsv", +"video/x-ogm+ogg", +"video/x-theora", +"video/x-theora+ogg", +"video/x-totem-stream", +NULL +}; +G_GNUC_UNUSED static const gchar *audio_mime_types[] = { +"audio/3gpp", +"audio/3gpp2", +"audio/aac", +"audio/ac3", +"audio/AMR", +"audio/AMR-WB", +"audio/basic", +"audio/dv", +"audio/eac3", +"audio/flac", +"audio/m4a", +"audio/midi", +"audio/mp1", +"audio/mp2", +"audio/mp3", +"audio/mp4", +"audio/mpeg", +"audio/mpg", +"audio/ogg", +"audio/opus", +"audio/prs.sid", +"audio/scpls", +"audio/vnd.rn-realaudio", +"audio/wav", +"audio/webm", +"audio/x-aac", +"audio/x-aiff", +"audio/x-ape", +"audio/x-flac", +"audio/x-gsm", +"audio/x-it", +"audio/x-m4a", +"audio/x-m4b", +"audio/x-matroska", +"audio/x-mod", +"audio/x-mp1", +"audio/x-mp2", +"audio/x-mp3", +"audio/x-mpg", +"audio/x-mpeg", +"audio/x-ms-asf", +"audio/x-ms-asx", +"audio/x-ms-wax", +"audio/x-ms-wma", +"audio/x-musepack", +"audio/x-opus+ogg", +"audio/x-pn-aiff", +"audio/x-pn-au", +"audio/x-pn-wav", +"audio/x-pn-windows-acm", +"audio/x-realaudio", +"audio/x-real-audio", +"audio/x-s3m", +"audio/x-sbc", +"audio/x-shorten", +"audio/x-speex", +"audio/x-stm", +"audio/x-tta", +"audio/x-wav", +"audio/x-wavpack", +"audio/x-vorbis", +"audio/x-vorbis+ogg", +"audio/x-xm", +"application/x-flac", +NULL +}; +G_GNUC_UNUSED static const gchar *video_mime_types[] = { +"application/mxf", +"application/ogg", +"application/ram", +"application/sdp", +"application/vnd.apple.mpegurl", +"application/vnd.ms-asf", +"application/vnd.ms-wpl", +"application/vnd.rn-realmedia", +"application/vnd.rn-realmedia-vbr", +"application/x-extension-m4a", +"application/x-extension-mp4", +"application/x-flash-video", +"application/x-matroska", +"application/x-netshow-channel", +"application/x-ogg", +"application/x-quicktimeplayer", +"application/x-shorten", +"image/vnd.rn-realpix", +"image/x-pict", +"misc/ultravox", +"text/x-google-video-pointer", +"video/3gp", +"video/3gpp", +"video/3gpp2", +"video/dv", +"video/divx", +"video/fli", +"video/flv", +"video/mp2t", +"video/mp4", +"video/mp4v-es", +"video/mpeg", +"video/mpeg-system", +"video/msvideo", +"video/ogg", +"video/quicktime", +"video/vivo", +"video/vnd.divx", +"video/vnd.mpegurl", +"video/vnd.rn-realvideo", +"video/vnd.vivo", +"video/webm", +"video/x-anim", +"video/x-avi", +"video/x-flc", +"video/x-fli", +"video/x-flic", +"video/x-flv", +"video/x-m4v", +"video/x-matroska", +"video/x-mjpeg", +"video/x-mpeg", +"video/x-mpeg2", +"video/x-ms-asf", +"video/x-ms-asf-plugin", +"video/x-ms-asx", +"video/x-msvideo", +"video/x-ms-wm", +"video/x-ms-wmv", +"video/x-ms-wmx", +"video/x-ms-wvx", +"video/x-nsv", +"video/x-ogm+ogg", +"video/x-theora", +"video/x-theora+ogg", +"video/x-totem-stream", +"audio/x-pn-realaudio", +NULL +}; diff --git a/extensions/audio-video-properties/totem-properties-main.c b/extensions/audio-video-properties/totem-properties-main.c new file mode 100644 index 0000000..2bbd520 --- /dev/null +++ b/extensions/audio-video-properties/totem-properties-main.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2000, 2001 Eazel Inc. + * Copyright (C) 2003 Andrew Sobala <aes@gnome.org> + * Copyright (C) 2005 Bastien Nocera <hadess@hadess.net> + * + * This library 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 library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> +#define GST_USE_UNSTABLE_API 1 +#include <gst/gst.h> + +#include "totem-properties-view.h" +#include "totem-gst-helpers.h" +#include <nautilus-extension.h> + +#define WANT_MIME_TYPES 1 +#include "totem-mime-types.h" + +static GType tpp_type = 0; +static void property_page_provider_iface_init + (NautilusPropertyPageProviderIface *iface); +static GList *totem_properties_get_pages + (NautilusPropertyPageProvider *provider, GList *files); + +static void +totem_properties_plugin_register_type (GTypeModule *module) +{ + const GTypeInfo info = { + sizeof (GObjectClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) NULL, + NULL, + NULL, + sizeof (GObject), + 0, + (GInstanceInitFunc) NULL + }; + const GInterfaceInfo property_page_provider_iface_info = { + (GInterfaceInitFunc)property_page_provider_iface_init, + NULL, + NULL + }; + + tpp_type = g_type_module_register_type (module, G_TYPE_OBJECT, + "TotemPropertiesPlugin", + &info, 0); + g_type_module_add_interface (module, + tpp_type, + NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER, + &property_page_provider_iface_info); +} + +static void +property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface) +{ + iface->get_pages = totem_properties_get_pages; +} + +static gpointer +init_backend (gpointer data) +{ + gst_init (NULL, NULL); + totem_gst_disable_display_decoders (); + return NULL; +} + +static GList * +totem_properties_get_pages (NautilusPropertyPageProvider *provider, + GList *files) +{ + static GOnce backend_inited = G_ONCE_INIT; + NautilusFileInfo *file; + char *uri; + GtkWidget *page, *label; + NautilusPropertyPage *property_page; + guint i; + gboolean found; + + /* only add properties page if a single file is selected */ + if (files == NULL || files->next != NULL) + return NULL; + file = files->data; + + /* only add the properties page to these mime types */ + found = FALSE; + for (i = 0; mime_types[i] != NULL; i++) { + if (nautilus_file_info_is_mime_type (file, mime_types[i])) { + found = TRUE; + break; + } + } + if (found == FALSE) + return NULL; + + /* okay, make the page, init'ing the backend first if necessary */ + g_once (&backend_inited, init_backend, NULL); + + uri = nautilus_file_info_get_uri (file); + label = gtk_label_new (_("Audio/Video")); + page = totem_properties_view_new (uri, label); + g_free (uri); + + gtk_container_set_border_width (GTK_CONTAINER (page), 6); + property_page = nautilus_property_page_new ("video-properties", + label, page); + + return g_list_prepend (NULL, property_page); +} + +/* --- extension interface --- */ +void +nautilus_module_initialize (GTypeModule *module) +{ + /* set up translation catalog */ + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + totem_properties_plugin_register_type (module); + totem_properties_view_register_type (module); +} + +void +nautilus_module_shutdown (void) +{ +} + +void +nautilus_module_list_types (const GType **types, + int *num_types) +{ + static GType type_list[1]; + + type_list[0] = tpp_type; + *types = type_list; + *num_types = G_N_ELEMENTS (type_list); +} + diff --git a/extensions/audio-video-properties/totem-properties-view.c b/extensions/audio-video-properties/totem-properties-view.c new file mode 100644 index 0000000..f280fa2 --- /dev/null +++ b/extensions/audio-video-properties/totem-properties-view.c @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2003 Andrew Sobala <aes@gnome.org> + * Copyright (C) 2004 Bastien Nocera <hadess@hadess.net> + * + * This library 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 library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <config.h> + +#include <gtk/gtk.h> +#include <glib/gi18n-lib.h> + +#define GST_USE_UNSTABLE_API 1 +#include <gst/tag/tag.h> +#include <gst/pbutils/pbutils.h> + +#include "totem-properties-view.h" +#include "bacon-video-widget-properties.h" + +struct TotemPropertiesViewPriv { + GtkWidget *label; + GtkWidget *vbox; + BaconVideoWidgetProperties *props; + GstDiscoverer *disco; +}; + +static GObjectClass *parent_class = NULL; +static void totem_properties_view_finalize (GObject *object); + +G_DEFINE_TYPE (TotemPropertiesView, totem_properties_view, GTK_TYPE_GRID) + +void +totem_properties_view_register_type (GTypeModule *module) +{ + totem_properties_view_get_type (); +} + +static void +totem_properties_view_class_init (TotemPropertiesViewClass *class) +{ + parent_class = g_type_class_peek_parent (class); + G_OBJECT_CLASS (class)->finalize = totem_properties_view_finalize; +} + +static void +update_general (TotemPropertiesView *props, + const GstTagList *list) +{ + struct { + const char *tag_name; + const char *widget; + } items[] = { + { GST_TAG_TITLE, "title" }, + { GST_TAG_ARTIST, "artist" }, + { GST_TAG_ALBUM, "album" }, + }; + guint i; + GDate *date; + GstDateTime *datetime; + gchar *comment; + + for (i = 0; i < G_N_ELEMENTS(items); i++) { + char *string; + + if (gst_tag_list_get_string_index (list, items[i].tag_name, 0, &string) != FALSE) { + bacon_video_widget_properties_set_label (props->priv->props, + items[i].widget, + string); + g_free (string); + } + } + + /* Comment else use Description defined by: + * http://xiph.org/vorbis/doc/v-comment.html */ + if (gst_tag_list_get_string (list, GST_TAG_COMMENT, &comment) || + gst_tag_list_get_string (list, GST_TAG_DESCRIPTION, &comment)) { + + bacon_video_widget_properties_set_label (props->priv->props, + "comment", + comment); + g_free (comment); + } + + /* Date */ + if (gst_tag_list_get_date (list, GST_TAG_DATE, &date)) { + char *string; + + string = g_strdup_printf ("%d", g_date_get_year (date)); + g_date_free (date); + bacon_video_widget_properties_set_label (props->priv->props, + "year", + string); + g_free (string); + } else if (gst_tag_list_get_date_time (list, GST_TAG_DATE_TIME, &datetime)) { + char *string; + + string = g_strdup_printf ("%d", gst_date_time_get_year (datetime)); + gst_date_time_unref (datetime); + bacon_video_widget_properties_set_label (props->priv->props, + "year", + string); + g_free (string); + } +} + +static void +set_codec (TotemPropertiesView *props, + GstDiscovererStreamInfo *info, + const char *widget) +{ + GstCaps *caps; + const char *nick; + + nick = gst_discoverer_stream_info_get_stream_type_nick (info); + if (g_str_equal (nick, "audio") == FALSE && + g_str_equal (nick, "video") == FALSE && + g_str_equal (nick, "container") == FALSE) { + bacon_video_widget_properties_set_label (props->priv->props, + widget, + _("N/A")); + return; + } + + caps = gst_discoverer_stream_info_get_caps (info); + if (caps) { + if (gst_caps_is_fixed (caps)) { + char *string; + + string = gst_pb_utils_get_codec_description (caps); + bacon_video_widget_properties_set_label (props->priv->props, + widget, + string); + g_free (string); + } + gst_caps_unref (caps); + } +} + +static void +set_bitrate (TotemPropertiesView *props, + guint bitrate, + const char *widget) +{ + char *string; + + if (!bitrate) { + bacon_video_widget_properties_set_label (props->priv->props, + widget, + C_("Stream bit rate", "N/A")); + return; + } + string = g_strdup_printf (_("%d kbps"), bitrate / 1000); + bacon_video_widget_properties_set_label (props->priv->props, + widget, + string); + g_free (string); +} + +static void +update_video (TotemPropertiesView *props, + GstDiscovererVideoInfo *info) +{ + guint width, height; + guint fps_n, fps_d; + char *string; + + width = gst_discoverer_video_info_get_width (info); + height = gst_discoverer_video_info_get_height (info); + string = g_strdup_printf (N_("%d × %d"), width, height); + bacon_video_widget_properties_set_label (props->priv->props, + "dimensions", + string); + g_free (string); + + set_codec (props, (GstDiscovererStreamInfo *) info, "vcodec"); + set_bitrate (props, gst_discoverer_video_info_get_bitrate (info), "video_bitrate"); + + /* Round up/down to the nearest integer framerate */ + fps_n = gst_discoverer_video_info_get_framerate_num (info); + fps_d = gst_discoverer_video_info_get_framerate_denom (info); + if (fps_d > 0.0) + bacon_video_widget_properties_set_framerate (props->priv->props, + (float) fps_n / (float) fps_d); + else + bacon_video_widget_properties_set_framerate (props->priv->props, 0.0); +} + +static void +update_audio (TotemPropertiesView *props, + GstDiscovererAudioInfo *info) +{ + guint samplerate, channels; + + set_codec (props, (GstDiscovererStreamInfo *) info, "acodec"); + + set_bitrate (props, gst_discoverer_audio_info_get_bitrate (info), "audio_bitrate"); + + samplerate = gst_discoverer_audio_info_get_sample_rate (info); + if (samplerate) { + char *string; + string = g_strdup_printf (_("%d Hz"), samplerate); + bacon_video_widget_properties_set_label (props->priv->props, + "samplerate", + string); + g_free (string); + } else { + bacon_video_widget_properties_set_label (props->priv->props, + "samplerate", + C_("Sample rate", "N/A")); + } + + channels = gst_discoverer_audio_info_get_channels (info); + if (channels) { + char *string; + + if (channels > 2) { + string = g_strdup_printf ("%s %d.1", _("Surround"), channels - 1); + } else if (channels == 1) { + string = g_strdup (_("Mono")); + } else if (channels == 2) { + string = g_strdup (_("Stereo")); + } else { + string = g_strdup (""); //Should not happen + } + bacon_video_widget_properties_set_label (props->priv->props, + "channels", + string); + g_free (string); + } else { + bacon_video_widget_properties_set_label (props->priv->props, + "channels", + C_("Number of audio channels", "N/A")); + } +} + +static void +discovered_cb (GstDiscoverer *discoverer, + GstDiscovererInfo *info, + GError *error, + TotemPropertiesView *props) +{ + GList *video_streams, *audio_streams; + const GstTagList *taglist; + gboolean has_audio, has_video; + const char *label; + GstClockTime duration; + GstDiscovererStreamInfo *sinfo; + + if (error) { + g_warning ("Couldn't get information about '%s': %s", + gst_discoverer_info_get_uri (info), + error->message); + return; + } + + video_streams = gst_discoverer_info_get_video_streams (info); + has_video = (video_streams != NULL); + audio_streams = gst_discoverer_info_get_audio_streams (info); + has_audio = (audio_streams != NULL); + + if (has_audio == has_video) + label = N_("Audio/Video"); + else if (has_audio) + label = N_("Audio"); + else + label = N_("Video"); + + gtk_label_set_text (GTK_LABEL (props->priv->label), _(label)); + + /* Widgets */ + bacon_video_widget_properties_set_has_type (props->priv->props, + has_video, + has_audio); + + /* General */ + duration = gst_discoverer_info_get_duration (info); + bacon_video_widget_properties_set_duration (props->priv->props, duration / GST_SECOND * 1000); + + sinfo = gst_discoverer_info_get_stream_info (info); + if (sinfo) { + set_codec (props, sinfo, "container"); + gst_discoverer_stream_info_unref (sinfo); + } + + taglist = gst_discoverer_info_get_tags (info); + update_general (props, taglist); + + /* Video and Audio */ + if (video_streams) + update_video (props, video_streams->data); + if (audio_streams) + update_audio (props, audio_streams->data); + + gst_discoverer_stream_info_list_free (video_streams); + gst_discoverer_stream_info_list_free (audio_streams); +} + +static void +totem_properties_view_init (TotemPropertiesView *props) +{ + GError *err = NULL; + + props->priv = g_new0 (TotemPropertiesViewPriv, 1); + + props->priv->vbox = bacon_video_widget_properties_new (); + gtk_grid_attach (GTK_GRID (props), props->priv->vbox, 0, 0, 1, 1); + gtk_widget_show (GTK_WIDGET (props)); + + props->priv->props = BACON_VIDEO_WIDGET_PROPERTIES (props->priv->vbox); + + props->priv->disco = gst_discoverer_new (GST_SECOND * 60, &err); + if (props->priv->disco == NULL) { + g_warning ("Could not create discoverer object: %s", err->message); + g_error_free (err); + return; + } + g_signal_connect (props->priv->disco, "discovered", + G_CALLBACK (discovered_cb), props); +} + +static void +totem_properties_view_finalize (GObject *object) +{ + TotemPropertiesView *props; + + props = TOTEM_PROPERTIES_VIEW (object); + + if (props->priv != NULL) { + if (props->priv->disco) { + g_signal_handlers_disconnect_by_func (props->priv->disco, + discovered_cb, + props); + gst_discoverer_stop (props->priv->disco); + g_clear_object (&props->priv->disco); + } + g_clear_object (&props->priv->label); + g_free (props->priv); + } + props->priv = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +totem_properties_view_set_location (TotemPropertiesView *props, + const char *location) +{ + g_assert (TOTEM_IS_PROPERTIES_VIEW (props)); + + if (props->priv->disco) + gst_discoverer_stop (props->priv->disco); + + bacon_video_widget_properties_reset (props->priv->props); + + if (location != NULL && props->priv->disco != NULL) { + gst_discoverer_start (props->priv->disco); + + if (gst_discoverer_discover_uri_async (props->priv->disco, location) == FALSE) { + g_warning ("Couldn't add %s to list", location); + return; + } + } +} + +GtkWidget * +totem_properties_view_new (const char *location, GtkWidget *label) +{ + TotemPropertiesView *self; + + self = g_object_new (TOTEM_TYPE_PROPERTIES_VIEW, NULL); + g_object_ref (label); + self->priv->label = label; + totem_properties_view_set_location (self, location); + + return GTK_WIDGET (self); +} diff --git a/extensions/audio-video-properties/totem-properties-view.h b/extensions/audio-video-properties/totem-properties-view.h new file mode 100644 index 0000000..0dc7292 --- /dev/null +++ b/extensions/audio-video-properties/totem-properties-view.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2003 Andrew Sobala <aes@gnome.org> + * Copyright (C) 2005 Bastien Nocera <hadess@hadess.net> + * + * This library 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 library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef TOTEM_PROPERTIES_VIEW_H +#define TOTEM_PROPERTIES_VIEW_H + +#include <gtk/gtk.h> + +#define TOTEM_TYPE_PROPERTIES_VIEW (totem_properties_view_get_type ()) +#define TOTEM_PROPERTIES_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TOTEM_TYPE_PROPERTIES_VIEW, TotemPropertiesView)) +#define TOTEM_PROPERTIES_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TOTEM_TYPE_PROPERTIES_VIEW, TotemPropertiesViewClass)) +#define TOTEM_IS_PROPERTIES_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TOTEM_TYPE_PROPERTIES_VIEW)) +#define TOTEM_IS_PROPERTIES_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TOTEM_TYPE_PROPERTIES_VIEW)) + +typedef struct TotemPropertiesViewPriv TotemPropertiesViewPriv; + +typedef struct { + GtkGrid parent; + TotemPropertiesViewPriv *priv; +} TotemPropertiesView; + +typedef struct { + GtkGridClass parent; +} TotemPropertiesViewClass; + +GType totem_properties_view_get_type (void); +void totem_properties_view_register_type (GTypeModule *module); + +GtkWidget *totem_properties_view_new (const char *location, + GtkWidget *label); + +#endif /* TOTEM_PROPERTIES_VIEW_H */ diff --git a/extensions/image-properties/meson.build b/extensions/image-properties/meson.build new file mode 100644 index 0000000..b292a19 --- /dev/null +++ b/extensions/image-properties/meson.build @@ -0,0 +1,15 @@ +shared_module ( + 'nautilus-image-properties', [ + 'nautilus-image-properties-module.c', + 'nautilus-image-properties-page.c', + 'nautilus-image-properties-page.h', + 'nautilus-image-properties-page-provider.c', + 'nautilus-image-properties-page-provider.h' + ], + dependencies: [ + gexiv, + nautilus_extension + ], + install: true, + install_dir: extensiondir +) diff --git a/extensions/image-properties/nautilus-image-properties-module.c b/extensions/image-properties/nautilus-image-properties-module.c new file mode 100644 index 0000000..0ce02e9 --- /dev/null +++ b/extensions/image-properties/nautilus-image-properties-module.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2018 Ernestas Kulik <ernestask@gnome.org> + * + * This file is part of Nautilus. + * + * Nautilus 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. + * + * Nautilus 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 Nautilus. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "nautilus-image-properties-page-provider.h" + +#include <glib/gi18n-lib.h> + +#include <nautilus-extension.h> + +void +nautilus_module_initialize (GTypeModule *module) +{ + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + nautilus_image_properties_page_provider_load (module); +} + +void +nautilus_module_shutdown (void) +{ +} + +void +nautilus_module_list_types (const GType **types, + int *num_types) +{ + static GType type_list[1] = { 0 }; + + g_assert (types != NULL); + g_assert (num_types != NULL); + + type_list[0] = NAUTILUS_TYPE_IMAGE_PROPERTIES_PAGE_PROVIDER; + + *types = type_list; + *num_types = G_N_ELEMENTS (type_list); +} diff --git a/extensions/image-properties/nautilus-image-properties-page-provider.c b/extensions/image-properties/nautilus-image-properties-page-provider.c new file mode 100644 index 0000000..b270ea9 --- /dev/null +++ b/extensions/image-properties/nautilus-image-properties-page-provider.c @@ -0,0 +1,136 @@ +/* Copyright (C) 2004 Red Hat, Inc + * Copyright (c) 2007 Novell, Inc. + * Copyright (c) 2017 Thomas Bechtold <thomasbechtold@jpberlin.de> + * Copyright (c) 2018 Ernestas Kulik <ernestask@gnome.org> + * + * 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, see <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + * XMP support by Hubert Figuiere <hfiguiere@novell.com> + */ + +#include "nautilus-image-properties-page-provider.h" + +#include "nautilus-image-properties-page.h" + +#include <glib/gi18n.h> + +#include <nautilus-extension.h> + +#define NAUTILUS_IMAGE_PROPERTIES_PAGE_NAME "NautilusImagePropertiesPage::property_page" + +struct _NautilusImagesPropertiesPageProvider +{ + GObject parent_instance; +}; + +static void property_page_provider_iface_init (NautilusPropertyPageProviderInterface *iface); + +G_DEFINE_DYNAMIC_TYPE_EXTENDED (NautilusImagesPropertiesPageProvider, + nautilus_image_properties_page_provider, + G_TYPE_OBJECT, + 0, + G_IMPLEMENT_INTERFACE_DYNAMIC (NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER, + property_page_provider_iface_init)) + +static gboolean +is_mime_type_supported (const char *mime_type) +{ + g_autoptr (GSList) formats = NULL; + + if (mime_type == NULL) + { + return FALSE; + } + + formats = gdk_pixbuf_get_formats (); + + for (GSList *l = formats; l != NULL; l = l->next) + { + g_auto (GStrv) mime_types = NULL; + + mime_types = gdk_pixbuf_format_get_mime_types (l->data); + if (mime_types == NULL) + { + continue; + } + + if (g_strv_contains ((const char * const *) mime_types, mime_type)) + { + return TRUE; + } + } + + return FALSE; +} + +static GList * +get_pages (NautilusPropertyPageProvider *provider, + GList *files) +{ + NautilusFileInfo *file_info; + g_autofree char *mime_type = NULL; + NautilusImagesPropertiesPage *image_properties_page; + NautilusPropertyPage *property_page; + + if (files == NULL || files->next != NULL) + { + return NULL; + } + + file_info = NAUTILUS_FILE_INFO (files->data); + mime_type = nautilus_file_info_get_mime_type (file_info); + if (!is_mime_type_supported (mime_type)) + { + return NULL; + } + image_properties_page = nautilus_image_properties_page_new (); + property_page = nautilus_property_page_new (NAUTILUS_IMAGE_PROPERTIES_PAGE_NAME, + gtk_label_new (_("Image")), + GTK_WIDGET (image_properties_page)); + + nautilus_image_properties_page_load_from_file_info (image_properties_page, file_info); + + return g_list_prepend (NULL, property_page); +} + +static void +property_page_provider_iface_init (NautilusPropertyPageProviderInterface *iface) +{ + iface->get_pages = get_pages; +} + +static void +nautilus_image_properties_page_provider_init (NautilusImagesPropertiesPageProvider *self) +{ + (void) self; +} + +static void +nautilus_image_properties_page_provider_class_init (NautilusImagesPropertiesPageProviderClass *klass) +{ + (void) klass; +} + +static void +nautilus_image_properties_page_provider_class_finalize (NautilusImagesPropertiesPageProviderClass *klass) +{ + (void) klass; +} + +void +nautilus_image_properties_page_provider_load (GTypeModule *module) +{ + nautilus_image_properties_page_provider_register_type (module); +} diff --git a/extensions/image-properties/nautilus-image-properties-page-provider.h b/extensions/image-properties/nautilus-image-properties-page-provider.h new file mode 100644 index 0000000..59fd6f9 --- /dev/null +++ b/extensions/image-properties/nautilus-image-properties-page-provider.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2018 Ernestas Kulik <ernestask@gnome.org> + * + * This file is part of Nautilus. + * + * Nautilus 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. + * + * Nautilus 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 Nautilus. If not, see <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <glib-object.h> + +#define NAUTILUS_TYPE_IMAGE_PROPERTIES_PAGE_PROVIDER (nautilus_image_properties_page_provider_get_type ()) + +G_DECLARE_FINAL_TYPE (NautilusImagesPropertiesPageProvider, + nautilus_image_properties_page_provider, + NAUTILUS, IMAGE_PROPERTIES_PAGE_PROVIDER, + GObject) + +void nautilus_image_properties_page_provider_load (GTypeModule *module);
\ No newline at end of file diff --git a/extensions/image-properties/nautilus-image-properties-page.c b/extensions/image-properties/nautilus-image-properties-page.c new file mode 100644 index 0000000..bca0b56 --- /dev/null +++ b/extensions/image-properties/nautilus-image-properties-page.c @@ -0,0 +1,515 @@ +/* Copyright (C) 2004 Red Hat, Inc + * Copyright (c) 2007 Novell, Inc. + * Copyright (c) 2017 Thomas Bechtold <thomasbechtold@jpberlin.de> + * + * 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, see <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + * XMP support by Hubert Figuiere <hfiguiere@novell.com> + */ + +#include "nautilus-image-properties-page.h" + +#include <gexiv2/gexiv2.h> +#include <glib/gi18n.h> + +#define LOAD_BUFFER_SIZE 8192 + +struct _NautilusImagesPropertiesPage +{ + GtkGrid parent; + + GCancellable *cancellable; + GtkWidget *grid; + GdkPixbufLoader *loader; + gboolean got_size; + gboolean pixbuf_still_loading; + unsigned char buffer[LOAD_BUFFER_SIZE]; + int width; + int height; + + GExiv2Metadata *md; + gboolean md_ready; +}; + +G_DEFINE_TYPE (NautilusImagesPropertiesPage, + nautilus_image_properties_page, + GTK_TYPE_GRID); + +static void +finalize (GObject *object) +{ + NautilusImagesPropertiesPage *page; + + page = NAUTILUS_IMAGE_PROPERTIES_PAGE (object); + + if (page->cancellable != NULL) + { + g_cancellable_cancel (page->cancellable); + g_clear_object (&page->cancellable); + } + + G_OBJECT_CLASS (nautilus_image_properties_page_parent_class)->finalize (object); +} + +static void +nautilus_image_properties_page_class_init (NautilusImagesPropertiesPageClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = finalize; +} + +static void +append_item (NautilusImagesPropertiesPage *page, + const char *name, + const char *value) +{ + GtkWidget *name_label; + PangoAttrList *attrs; + + name_label = gtk_label_new (name); + attrs = pango_attr_list_new (); + + pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); + gtk_label_set_attributes (GTK_LABEL (name_label), attrs); + pango_attr_list_unref (attrs); + gtk_container_add (GTK_CONTAINER (page->grid), name_label); + gtk_widget_set_halign (name_label, GTK_ALIGN_START); + gtk_widget_show (name_label); + + if (value != NULL) + { + GtkWidget *value_label; + + value_label = gtk_label_new (value); + + gtk_label_set_line_wrap (GTK_LABEL (value_label), TRUE); + gtk_grid_attach_next_to (GTK_GRID (page->grid), value_label, + name_label, GTK_POS_RIGHT, + 1, 1); + gtk_widget_set_halign (value_label, GTK_ALIGN_START); + gtk_widget_set_hexpand (value_label, TRUE); + gtk_widget_show (value_label); + } +} + +static void +nautilus_image_properties_page_init (NautilusImagesPropertiesPage *self) +{ + GtkWidget *scrolled_window; + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + + gtk_widget_set_vexpand (GTK_WIDGET (scrolled_window), TRUE); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + + gtk_container_add (GTK_CONTAINER (self), scrolled_window); + + self->grid = gtk_grid_new (); + + gtk_orientable_set_orientation (GTK_ORIENTABLE (self->grid), GTK_ORIENTATION_VERTICAL); + gtk_grid_set_row_spacing (GTK_GRID (self->grid), 6); + gtk_grid_set_column_spacing (GTK_GRID (self->grid), 18); + append_item (self, _("Loading…"), NULL); + gtk_container_add (GTK_CONTAINER (scrolled_window), self->grid); + + gtk_widget_show_all (GTK_WIDGET (self)); +} + +static void +append_basic_info (NautilusImagesPropertiesPage *page) +{ + GdkPixbufFormat *format; + g_autofree char *name = NULL; + g_autofree char *desc = NULL; + g_autofree char *value = NULL; + + format = gdk_pixbuf_loader_get_format (page->loader); + name = gdk_pixbuf_format_get_name (format); + desc = gdk_pixbuf_format_get_description (format); + value = g_strdup_printf ("%s (%s)", name, desc); + + append_item (page, _("Image Type"), value); + + g_free (value); + value = g_strdup_printf (ngettext ("%d pixel", + "%d pixels", + page->width), + page->width); + + append_item (page, _("Width"), value); + + g_free (value); + value = g_strdup_printf (ngettext ("%d pixel", + "%d pixels", + page->height), + page->height); + + append_item (page, _("Height"), value); +} + +static void +append_gexiv2_tag (NautilusImagesPropertiesPage *page, + const char **tag_names, + const char *description) +{ + g_assert (tag_names != NULL); + + for (const char **i = tag_names; *i != NULL; i++) + { + if (gexiv2_metadata_has_tag (page->md, *i)) + { + g_autofree char *tag_value = NULL; + + tag_value = gexiv2_metadata_get_tag_interpreted_string (page->md, *i); + + if (description == NULL) + { + description = gexiv2_metadata_get_tag_description (*i); + } + + /* don't add empty tags - try next one */ + if (strlen (tag_value) > 0) + { + append_item (page, description, tag_value); + break; + } + } + } +} + +static void +append_gexiv2_info (NautilusImagesPropertiesPage *page) +{ + double longitude; + double latitude; + double altitude; + + /* define tags and its alternatives */ + const char *title[] = { "Xmp.dc.title", NULL }; + const char *camera_brand[] = { "Exif.Image.Make", NULL }; + const char *camera_model[] = { "Exif.Image.Model", "Exif.Image.UniqueCameraModel", NULL }; + const char *created_on[] = { "Exif.Photo.DateTimeOriginal", "Xmp.xmp.CreateDate", "Exif.Image.DateTime", NULL }; + const char *exposure_time[] = { "Exif.Photo.ExposureTime", NULL }; + const char *aperture_value[] = { "Exif.Photo.ApertureValue", NULL }; + const char *iso_speed_ratings[] = { "Exif.Photo.ISOSpeedRatings", "Xmp.exifEX.ISOSpeed", NULL }; + const char *flash[] = { "Exif.Photo.Flash", NULL }; + const char *metering_mode[] = { "Exif.Photo.MeteringMode", NULL }; + const char *exposure_mode[] = { "Exif.Photo.ExposureMode", NULL }; + const char *focal_length[] = { "Exif.Photo.FocalLength", NULL }; + const char *software[] = { "Exif.Image.Software", NULL }; + const char *description[] = { "Xmp.dc.description", "Exif.Photo.UserComment", NULL }; + const char *subject[] = { "Xmp.dc.subject", NULL }; + const char *creator[] = { "Xmp.dc.creator", "Exif.Image.Artist", NULL }; + const char *rights[] = { "Xmp.dc.rights", NULL }; + const char *rating[] = { "Xmp.xmp.Rating", NULL }; + + if (!page->md_ready) + { + return; + } + + append_gexiv2_tag (page, camera_brand, _("Camera Brand")); + append_gexiv2_tag (page, camera_model, _("Camera Model")); + append_gexiv2_tag (page, exposure_time, _("Exposure Time")); + append_gexiv2_tag (page, exposure_mode, _("Exposure Program")); + append_gexiv2_tag (page, aperture_value, _("Aperture Value")); + append_gexiv2_tag (page, iso_speed_ratings, _("ISO Speed Rating")); + append_gexiv2_tag (page, flash, _("Flash Fired")); + append_gexiv2_tag (page, metering_mode, _("Metering Mode")); + append_gexiv2_tag (page, focal_length, _("Focal Length")); + append_gexiv2_tag (page, software, _("Software")); + append_gexiv2_tag (page, title, _("Title")); + append_gexiv2_tag (page, description, _("Description")); + append_gexiv2_tag (page, subject, _("Keywords")); + append_gexiv2_tag (page, creator, _("Creator")); + append_gexiv2_tag (page, created_on, _("Created On")); + append_gexiv2_tag (page, rights, _("Copyright")); + append_gexiv2_tag (page, rating, _("Rating")); + + if (gexiv2_metadata_get_gps_info (page->md, &longitude, &latitude, &altitude)) + { + g_autofree char *gps_coords = NULL; + + /* Translators: These are the coordinates of a position where a picture was taken. */ + gps_coords = g_strdup_printf (_("%f N / %f W (%.0f m)"), latitude, longitude, altitude); + + append_item (page, _("Coordinates"), gps_coords); + } +} + +static void +load_finished (NautilusImagesPropertiesPage *page) +{ + GtkWidget *label; + + label = gtk_grid_get_child_at (GTK_GRID (page->grid), 0, 0); + gtk_container_remove (GTK_CONTAINER (page->grid), label); + + if (page->loader != NULL) + { + gdk_pixbuf_loader_close (page->loader, NULL); + } + + if (page->got_size) + { + append_basic_info (page); + append_gexiv2_info (page); + } + else + { + append_item (page, _("Failed to load image information"), NULL); + } + + if (page->loader != NULL) + { + g_object_unref (page->loader); + page->loader = NULL; + } + page->md_ready = FALSE; + g_clear_object (&page->md); +} + +static void +file_close_callback (GObject *object, + GAsyncResult *res, + gpointer data) +{ + NautilusImagesPropertiesPage *page; + GInputStream *stream; + + page = data; + stream = G_INPUT_STREAM (object); + + g_input_stream_close_finish (stream, res, NULL); + + g_clear_object (&page->cancellable); +} + +static void +file_read_callback (GObject *object, + GAsyncResult *res, + gpointer data) +{ + NautilusImagesPropertiesPage *page; + GInputStream *stream; + g_autoptr (GError) error = NULL; + gssize count_read; + gboolean done_reading; + + page = data; + stream = G_INPUT_STREAM (object); + count_read = g_input_stream_read_finish (stream, res, &error); + done_reading = FALSE; + + if (count_read > 0) + { + g_assert (count_read <= sizeof (page->buffer)); + + if (page->pixbuf_still_loading) + { + if (!gdk_pixbuf_loader_write (page->loader, + page->buffer, + count_read, + NULL)) + { + page->pixbuf_still_loading = FALSE; + } + } + + if (page->pixbuf_still_loading) + { + g_input_stream_read_async (G_INPUT_STREAM (stream), + page->buffer, + sizeof (page->buffer), + G_PRIORITY_DEFAULT, + page->cancellable, + file_read_callback, + page); + } + else + { + done_reading = TRUE; + } + } + else + { + /* either EOF, cancelled or an error occurred */ + done_reading = TRUE; + } + + if (error != NULL) + { + g_autofree char *uri = NULL; + + uri = g_file_get_uri (G_FILE (object)); + + g_warning ("Error reading %s: %s", uri, error->message); + } + + if (done_reading) + { + load_finished (page); + g_input_stream_close_async (stream, + G_PRIORITY_DEFAULT, + page->cancellable, + file_close_callback, + page); + } +} + +static void +size_prepared_callback (GdkPixbufLoader *loader, + int width, + int height, + gpointer callback_data) +{ + NautilusImagesPropertiesPage *page; + + page = callback_data; + + page->height = height; + page->width = width; + page->got_size = TRUE; + page->pixbuf_still_loading = FALSE; +} + +typedef struct +{ + NautilusImagesPropertiesPage *page; + NautilusFileInfo *file_info; +} FileOpenData; + +static void +file_open_callback (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + g_autofree FileOpenData *data = NULL; + NautilusImagesPropertiesPage *page; + GFile *file; + g_autofree char *uri = NULL; + g_autoptr (GError) error = NULL; + g_autoptr (GFileInputStream) stream = NULL; + + data = user_data; + page = data->page; + file = G_FILE (object); + uri = g_file_get_uri (file); + stream = g_file_read_finish (file, res, &error); + if (stream != NULL) + { + g_autofree char *mime_type = NULL; + + mime_type = nautilus_file_info_get_mime_type (data->file_info); + + page->loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, &error); + if (error != NULL) + { + g_warning ("Error creating loader for %s: %s", uri, error->message); + } + page->pixbuf_still_loading = TRUE; + page->width = 0; + page->height = 0; + + g_signal_connect (page->loader, + "size-prepared", + G_CALLBACK (size_prepared_callback), + page); + + g_input_stream_read_async (G_INPUT_STREAM (stream), + page->buffer, + sizeof (page->buffer), + G_PRIORITY_DEFAULT, + page->cancellable, + file_read_callback, + page); + } + else + { + g_warning ("Error reading %s: %s", uri, error->message); + load_finished (page); + } +} + +void +nautilus_image_properties_page_load_from_file_info (NautilusImagesPropertiesPage *self, + NautilusFileInfo *file_info) +{ + g_autofree char *uri = NULL; + g_autoptr (GFile) file = NULL; + g_autofree char *path = NULL; + FileOpenData *data; + + g_return_if_fail (NAUTILUS_IS_IMAGE_PROPERTIES_PAGE (self)); + g_return_if_fail (file_info != NULL); + + self->cancellable = g_cancellable_new (); + + uri = nautilus_file_info_get_uri (file_info); + file = g_file_new_for_uri (uri); + path = g_file_get_path (file); + + /* gexiv2 metadata init */ + self->md_ready = gexiv2_initialize (); + if (!self->md_ready) + { + g_warning ("Unable to initialize gexiv2"); + } + else + { + self->md = gexiv2_metadata_new (); + if (path != NULL) + { + g_autoptr (GError) error = NULL; + + if (!gexiv2_metadata_open_path (self->md, path, &error)) + { + g_warning ("gexiv2 metadata not supported for '%s': %s", path, error->message); + self->md_ready = FALSE; + } + } + else + { + self->md_ready = FALSE; + } + } + + data = g_new0 (FileOpenData, 1); + + data->page = self; + data->file_info = file_info; + + g_file_read_async (file, + G_PRIORITY_DEFAULT, + self->cancellable, + file_open_callback, + data); +} + +NautilusImagesPropertiesPage * +nautilus_image_properties_page_new (void) +{ + return g_object_new (NAUTILUS_TYPE_IMAGE_PROPERTIES_PAGE, + "margin-bottom", 6, + "margin-end", 12, + "margin-start", 12, + "margin-top", 6, + NULL); +} diff --git a/extensions/image-properties/nautilus-image-properties-page.h b/extensions/image-properties/nautilus-image-properties-page.h new file mode 100644 index 0000000..5a2c358 --- /dev/null +++ b/extensions/image-properties/nautilus-image-properties-page.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2004 Red Hat, 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, see <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#pragma once + +#include <gtk/gtk.h> + +#include <nautilus-extension.h> + +#define NAUTILUS_TYPE_IMAGE_PROPERTIES_PAGE (nautilus_image_properties_page_get_type ()) + +G_DECLARE_FINAL_TYPE (NautilusImagesPropertiesPage, + nautilus_image_properties_page, + NAUTILUS, IMAGE_PROPERTIES_PAGE, + GtkGrid) + +void nautilus_image_properties_page_load_from_file_info (NautilusImagesPropertiesPage *page, + NautilusFileInfo *file_info); + +NautilusImagesPropertiesPage *nautilus_image_properties_page_new (void);
\ No newline at end of file diff --git a/extensions/meson.build b/extensions/meson.build new file mode 100644 index 0000000..5c6f64c --- /dev/null +++ b/extensions/meson.build @@ -0,0 +1,3 @@ +subdir('image-properties') +subdir('audio-video-properties') +subdir('sendto') diff --git a/extensions/sendto/meson.build b/extensions/sendto/meson.build new file mode 100644 index 0000000..3b73bcd --- /dev/null +++ b/extensions/sendto/meson.build @@ -0,0 +1,13 @@ +libnautilus_sendto_sources = [ + 'nautilus-nste.c', + 'nautilus-nste.h', + 'nautilus-sendto-module.c' +] + +libnautilus_sendto = shared_module( + 'nautilus-sendto', + libnautilus_sendto_sources, + dependencies: nautilus_extension, + install: true, + install_dir: extensiondir +) diff --git a/extensions/sendto/nautilus-nste.c b/extensions/sendto/nautilus-nste.c new file mode 100644 index 0000000..1e92800 --- /dev/null +++ b/extensions/sendto/nautilus-nste.c @@ -0,0 +1,159 @@ +/* + * Nautilus-sendto + * + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * This library 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * Author: Roberto Majadas <roberto.majadas@openshine.com> + * + */ + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> +#include <nautilus-extension.h> +#include "nautilus-nste.h" + +struct _NautilusNste +{ + GObject parent_instance; + + gboolean nst_present; +}; + +static void menu_provider_iface_init (NautilusMenuProviderInterface *iface); + +G_DEFINE_DYNAMIC_TYPE_EXTENDED (NautilusNste, nautilus_nste, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE_DYNAMIC (NAUTILUS_TYPE_MENU_PROVIDER, + menu_provider_iface_init)) + +static void +sendto_callback (NautilusMenuItem *item, + gpointer user_data) +{ + GList *files; + g_autoptr (GString) command = NULL; + + files = g_object_get_data (G_OBJECT (item), "files"); + command = g_string_new ("nautilus-sendto"); + + for (GList *l = files; l != NULL; l = l->next) + { + g_autofree char *uri = NULL; + + uri = nautilus_file_info_get_uri (l->data); + + g_string_append_printf (command, " \"%s\"", uri); + } + + g_spawn_command_line_async (command->str, NULL); +} + +static gboolean +check_available_mailer (void) +{ + g_autoptr (GAppInfo) app_info = NULL; + + app_info = g_app_info_get_default_for_uri_scheme ("mailto"); + + return app_info != NULL; +} + +static GList * +get_file_items (NautilusMenuProvider *provider, + GtkWidget *window, + GList *files) +{ + GList *items = NULL; + gboolean one_item; + NautilusMenuItem *item; + NautilusNste *nste; + + nste = NAUTILUS_NSTE (provider); + if (!nste->nst_present) + { + return NULL; + } + + if (files == NULL) + { + return NULL; + } + + if (!check_available_mailer ()) + { + return NULL; + } + + one_item = (files != NULL) && (files->next == NULL); + if (one_item && + !nautilus_file_info_is_directory ((NautilusFileInfo *) files->data)) + { + item = nautilus_menu_item_new ("NautilusNste::sendto", + _("Send to…"), + _("Send file by mail…"), + "document-send"); + } + else + { + item = nautilus_menu_item_new ("NautilusNste::sendto", + _("Send to…"), + _("Send files by mail…"), + "document-send"); + } + g_signal_connect (item, + "activate", + G_CALLBACK (sendto_callback), + provider); + g_object_set_data_full (G_OBJECT (item), + "files", + nautilus_file_info_list_copy (files), + (GDestroyNotify) nautilus_file_info_list_free); + + items = g_list_append (items, item); + + return items; +} + +static void +menu_provider_iface_init (NautilusMenuProviderInterface *iface) +{ + iface->get_file_items = get_file_items; +} + +static void +nautilus_nste_init (NautilusNste *nste) +{ + g_autofree char *path = NULL; + + path = g_find_program_in_path ("nautilus-sendto"); + nste->nst_present = (path != NULL); +} + +static void +nautilus_nste_class_init (NautilusNsteClass *klass) +{ +} + +static void +nautilus_nste_class_finalize (NautilusNsteClass *klass) +{ +} + +void +nautilus_nste_load (GTypeModule *module) +{ + nautilus_nste_register_type (module); +} diff --git a/extensions/sendto/nautilus-nste.h b/extensions/sendto/nautilus-nste.h new file mode 100644 index 0000000..46f7104 --- /dev/null +++ b/extensions/sendto/nautilus-nste.h @@ -0,0 +1,35 @@ +/* + * Nautilus SendTo extension + * + * Copyright (C) 2005 Roberto Majadas + * + * This library 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * Author: Roberto Majadas <roberto.majadas@openshine.com> + * + */ + +#pragma once + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_NSTE (nautilus_nste_get_type ()) + +G_DECLARE_FINAL_TYPE (NautilusNste, nautilus_nste, NAUTILUS, NSTE, GObject) + +void nautilus_nste_load (GTypeModule *module); + +G_END_DECLS
\ No newline at end of file diff --git a/extensions/sendto/nautilus-sendto-module.c b/extensions/sendto/nautilus-sendto-module.c new file mode 100644 index 0000000..524a34b --- /dev/null +++ b/extensions/sendto/nautilus-sendto-module.c @@ -0,0 +1,53 @@ +/* + * Nautilus SendTo + * + * Copyright (C) 2005 Roberto Majadas + * + * This library 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * Author: Roberto Majadas <roberto.majadas@openshine.com> + * + */ + +#include <config.h> +#include <nautilus-extension.h> +#include <glib/gi18n-lib.h> +#include "nautilus-nste.h" + + +void +nautilus_module_initialize (GTypeModule *module) +{ + nautilus_nste_load (module); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +} + +void +nautilus_module_shutdown (void) +{ +} + +void +nautilus_module_list_types (const GType **types, + int *num_types) +{ + static GType type_list[1]; + + type_list[0] = NAUTILUS_TYPE_NSTE; + *types = type_list; + + *num_types = 1; +} |