diff options
author | Bastien Nocera <hadess@hadess.net> | 2019-02-11 13:17:35 +0100 |
---|---|---|
committer | Carlos Soriano <csoriano@redhat.com> | 2019-02-11 16:03:55 +0100 |
commit | e9bb1cff992329bf182f511380bac015d0db2f14 (patch) | |
tree | fa34719f6eb7d90adce08985aef2978b860f8b0f /extensions | |
parent | 8078950532922c78f35cb7140be0567c0f413d3c (diff) | |
download | nautilus-e9bb1cff992329bf182f511380bac015d0db2f14.tar.gz |
Add copy/paste of totem's properties window nautilus extension
The code is quite stable and this is basic functionality which is going to be
better in Nautilus rather than relying on extensions, given the quite bad
extension system Nautilus has.
This will also help with the port to gtk4, so we rely in yet another important
extension providing properties pages (which in turn export gtk3 widgets).
Diffstat (limited to 'extensions')
11 files changed, 2042 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 000000000..d5621b676 --- /dev/null +++ b/extensions/audio-video-properties/bacon-video-widget-properties.c @@ -0,0 +1,284 @@ +/* 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 "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", _("Unknown")); + /* Artist */ + bacon_video_widget_properties_set_label (props, "artist", _("Unknown")); + /* Album */ + bacon_video_widget_properties_set_label (props, "album", _("Unknown")); + /* Year */ + bacon_video_widget_properties_set_label (props, "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", _("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, + int framerate) +{ + gchar *temp; + + g_return_if_fail (props != NULL); + g_return_if_fail (BACON_IS_VIDEO_WIDGET_PROPERTIES (props)); + + /* The FPS has to be done differently because it's a plural string */ + if (framerate != 0) { + temp = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d frame per second", "%d frames per second", 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 000000000..cef7e53e9 --- /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, + int 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 000000000..4ac5cd87d --- /dev/null +++ b/extensions/audio-video-properties/meson.build @@ -0,0 +1,48 @@ +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', +) + +libtotem_properties_page_sources = files( + 'totem-properties-main.c', + 'totem-properties-view.c', + 'bacon-video-widget-properties.c', +) + resources + +libtotem_properties_page_deps = [ + 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', + '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 000000000..d7f727dd6 --- /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 000000000..eed91f9f8 --- /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">Framerate:</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">Bitrate:</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">Bitrate:</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 000000000..124f6db8e --- /dev/null +++ b/extensions/audio-video-properties/test-properties-page.c @@ -0,0 +1,79 @@ +/* + * 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-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); + + 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-mime-types.h b/extensions/audio-video-properties/totem-mime-types.h new file mode 100644 index 000000000..6551f3199 --- /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 000000000..576198ea8 --- /dev/null +++ b/extensions/audio-video-properties/totem-properties-main.c @@ -0,0 +1,152 @@ +/* + * 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 <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); + 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 000000000..eb8bcf00b --- /dev/null +++ b/extensions/audio-video-properties/totem-properties-view.c @@ -0,0 +1,387 @@ +/* + * 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) + bacon_video_widget_properties_set_framerate (props->priv->props, 0); + else + bacon_video_widget_properties_set_framerate (props->priv->props, + (fps_n + fps_d/2) / fps_d); +} + +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")); + } + 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 000000000..0dc729240 --- /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/meson.build b/extensions/meson.build index 41048589c..5c6f64cef 100644 --- a/extensions/meson.build +++ b/extensions/meson.build @@ -1,2 +1,3 @@ subdir('image-properties') +subdir('audio-video-properties') subdir('sendto') |