diff options
author | Bastien Nocera <hadess@hadess.net> | 2019-02-08 12:46:55 +0100 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2019-02-08 15:34:40 +0100 |
commit | c3d8faeb6a19460afbddd310578db0f372c5e1c9 (patch) | |
tree | bfbcfcf1a1d7daa12a54719d9360e58fd6f25229 /src/plugins/rotation | |
parent | 8c943126d96a5081f40847bb02acb5b9cc21f4f9 (diff) | |
download | totem-c3d8faeb6a19460afbddd310578db0f372c5e1c9.tar.gz |
rotation: Port plugin to C
So we don't need to rely on Vala to build what is a core functionality.
Also mark it as builtin, evidently.
Diffstat (limited to 'src/plugins/rotation')
-rw-r--r-- | src/plugins/rotation/bacon-video.vapi | 19 | ||||
-rw-r--r-- | src/plugins/rotation/meson.build | 27 | ||||
-rw-r--r-- | src/plugins/rotation/rotation.plugin.desktop.in | 1 | ||||
-rw-r--r-- | src/plugins/rotation/totem-rotation-plugin.vala | 184 | ||||
-rw-r--r-- | src/plugins/rotation/totem-rotation.c | 294 |
5 files changed, 299 insertions, 226 deletions
diff --git a/src/plugins/rotation/bacon-video.vapi b/src/plugins/rotation/bacon-video.vapi deleted file mode 100644 index e3b25b3f4..000000000 --- a/src/plugins/rotation/bacon-video.vapi +++ /dev/null @@ -1,19 +0,0 @@ -[CCode (cprefix = "Bacon", lower_case_cprefix = "bacon_")] - -namespace Bacon { - [CCode (cheader_filename = "bacon-video-widget.h")] - public class VideoWidget : Gtk.Widget { - [CCode (has_construct_function = false)] - public VideoWidget () throws GLib.Error; - - public Rotation get_rotation (); - public void set_rotation (Rotation rotation); - } - [CCode (cname="BvwRotation", cprefix = "BVW_ROTATION_", cheader_filename = "bacon-video-widget.h")] - public enum Rotation { - R_ZERO = 0, - R_90R = 1, - R_180 = 2, - R_90L = 3 - } -} diff --git a/src/plugins/rotation/meson.build b/src/plugins/rotation/meson.build index 18068c27b..fc3a1b12f 100644 --- a/src/plugins/rotation/meson.build +++ b/src/plugins/rotation/meson.build @@ -2,31 +2,12 @@ plugin_name = 'rotation' plugin_dir = join_paths(totem_pluginsdir, plugin_name) -plugin_files = files( - 'totem-' + plugin_name + '-plugin.vala', - 'bacon-video.vapi' -) - -plugin_deps = [ - gtk_dep, - peas_dep, - dependency('cogl-pango-1.0'), - clutter_gtk_dep, -] - shared_module( plugin_name, - sources: plugin_files, - include_directories: plugins_incs + [ - backend_inc, - src_inc - ], - dependencies: plugin_deps + plugins_vala_deps, - c_args: plugins_cflags + plugins_vala_flags + [ - '--include=config.h' - ], - vala_args: plugins_vala_args, - link_with: libtotem, + sources: 'totem-' + plugin_name + '.c', + include_directories: plugins_incs, + dependencies: plugins_deps, + c_args: plugins_cflags, install: true, install_dir: plugin_dir ) diff --git a/src/plugins/rotation/rotation.plugin.desktop.in b/src/plugins/rotation/rotation.plugin.desktop.in index 5eadb7a82..46937c8e0 100644 --- a/src/plugins/rotation/rotation.plugin.desktop.in +++ b/src/plugins/rotation/rotation.plugin.desktop.in @@ -1,6 +1,7 @@ [Plugin] Module=rotation IAge=1 +Builtin=true Name=Rotation Plugin Description=Allows videos to be rotated if they are in the wrong orientation Authors=Simon Wenner <simon@wenner.ch> diff --git a/src/plugins/rotation/totem-rotation-plugin.vala b/src/plugins/rotation/totem-rotation-plugin.vala deleted file mode 100644 index 7a06d4ca1..000000000 --- a/src/plugins/rotation/totem-rotation-plugin.vala +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) Simon Wenner 2011 <simon@wenner.ch> - * - * 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 Library 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 - */ - -using GLib; -using Totem; -using Peas; - -public const string GIO_ROTATION_FILE_ATTRIBUTE = "metadata::totem::rotation"; - -class RotationPlugin: GLib.Object, Peas.Activatable -{ - private const int STATE_COUNT = 4; - public GLib.Object object { owned get; construct; } - private Bacon.VideoWidget bvw = null; - private GLib.SimpleAction rotate_left_action = null; - private GLib.SimpleAction rotate_right_action = null; - - public void activate () - { - Totem.Object t = (Totem.Object) this.object; - string mrl = t.get_current_mrl (); - GLib.Menu menu = t.get_menu_section ("rotation-placeholder"); - - this.bvw = t.get_video_widget () as Bacon.VideoWidget; - - // add interface elements to control the rotation - this.rotate_left_action = new GLib.SimpleAction ("rotate-left", null); - this.rotate_left_action.activate.connect (this.cb_rotate_left); - t.add_action (this.rotate_left_action); - t.add_accelerator("<Primary><Shift>R", "app.rotate-left", null); - - this.rotate_right_action = new GLib.SimpleAction ("rotate-right", null); - this.rotate_right_action.activate.connect (this.cb_rotate_right); - t.add_action (this.rotate_right_action); - t.add_accelerator("<Primary>R", "app.rotate-right", null); - - GLib.MenuItem item = new GLib.MenuItem (_("_Rotate ↷"), "app.rotate-right"); - item.set_attribute ("accel", "s", "<Primary>R"); - menu.append_item (item); - - item = new GLib.MenuItem (_("Rotate ↶"), "app.rotate-left"); - item.set_attribute ("accel", "s", "<Primary><Shift>R"); - menu.append_item (item); - - if (mrl == null) { - this.rotate_right_action.set_enabled (false); - this.rotate_left_action.set_enabled (false); - } - - // read the state of the current video from the GIO attribute - if (mrl != null) { - this.try_restore_state.begin (mrl, (o, r) => { - this.try_restore_state.end (r); - }); - } - - t.file_closed.connect (this.cb_file_closed); - t.file_opened.connect (this.cb_file_opened); - } - - public void deactivate () - { - Totem.Object t = (Totem.Object) this.object; - - // disconnect callbacks - t.file_closed.disconnect (this.cb_file_closed); - t.file_opened.disconnect (this.cb_file_opened); - - // remove interface elements to control the rotation - t.empty_menu_section ("rotation-placeholder"); - - // remove accelerators - t.remove_accelerator("app.rotate-right", null); - t.remove_accelerator("app.rotate-left", null); - - // undo transformations - this.bvw.set_rotation (Bacon.Rotation.R_ZERO); - } - - public void update_state () - { - //no-op - } - - private void cb_rotate_left () - { - int state = (this.bvw.get_rotation() - 1) % STATE_COUNT; - this.bvw.set_rotation ((Bacon.Rotation) state); - this.store_state.begin ((o, r) => { this.store_state.end (r); }); - } - - private void cb_rotate_right () - { - int state = (this.bvw.get_rotation() + 1) % STATE_COUNT; - this.bvw.set_rotation ((Bacon.Rotation) state); - this.store_state.begin ((o, r) => { this.store_state.end (r); }); - } - - private void cb_file_closed () - { - // reset the rotation - this.bvw.set_rotation (Bacon.Rotation.R_ZERO); - this.rotate_right_action.set_enabled (false); - this.rotate_left_action.set_enabled (false); - } - - private void cb_file_opened (string mrl) - { - this.rotate_right_action.set_enabled (true); - this.rotate_left_action.set_enabled (true); - this.try_restore_state.begin (mrl, (o, r) => { - this.try_restore_state.end (r); - }); - } - - private async void store_state () - { - Totem.Object t = (Totem.Object) this.object; - string mrl = t.get_current_mrl (); - - if (mrl == null) { - return; - } - - var file = GLib.File.new_for_uri (mrl); - try { - Bacon.Rotation rotation; - var file_info = yield file.query_info_async (GIO_ROTATION_FILE_ATTRIBUTE, - GLib.FileQueryInfoFlags.NONE); - - string state_str = ""; - rotation = this.bvw.get_rotation (); - if (rotation != Bacon.Rotation.R_ZERO) { - state_str = "%u".printf ((uint) rotation); - } - file_info.set_attribute_string (GIO_ROTATION_FILE_ATTRIBUTE, state_str); - yield file.set_attributes_async (file_info, GLib.FileQueryInfoFlags.NONE, - GLib.Priority.DEFAULT, null, null); - } catch (IOError.NOT_SUPPORTED e) { - } catch (GLib.Error e) { - GLib.warning ("Could not store file attribute: %s", e.message); - } - } - - private async void try_restore_state (string mrl) - { - var file = GLib.File.new_for_uri (mrl); - if (file.has_uri_scheme ("http") || file.has_uri_scheme ("dvd")) - return; - try { - var file_info = yield file.query_info_async (GIO_ROTATION_FILE_ATTRIBUTE, - GLib.FileQueryInfoFlags.NONE); - string state_str = file_info.get_attribute_string (GIO_ROTATION_FILE_ATTRIBUTE); - if (state_str != null) { - int state = (Bacon.Rotation) uint64.parse (state_str); - this.bvw.set_rotation ((Bacon.Rotation) state); - } - } catch (IOError.NOT_SUPPORTED e) { - } catch (GLib.Error e) { - GLib.warning ("Could not query file attribute: %s", e.message); - } - } -} - -[ModuleInit] -public void peas_register_types (GLib.TypeModule module) { - var objmodule = module as Peas.ObjectModule; - objmodule.register_extension_type (typeof (Peas.Activatable), typeof (RotationPlugin)); -} diff --git a/src/plugins/rotation/totem-rotation.c b/src/plugins/rotation/totem-rotation.c new file mode 100644 index 000000000..db342df23 --- /dev/null +++ b/src/plugins/rotation/totem-rotation.c @@ -0,0 +1,294 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) Bastien Nocera 2019 <hadess@hadess.net> + * Copyright (C) Simon Wenner 2011 <simon@wenner.ch> + * + * 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 Library 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 "config.h" + +#include <unistd.h> + +#include <glib.h> +#include <glib-object.h> +#include <glib/gi18n-lib.h> +#include <glib/gstdio.h> +#include <gmodule.h> +#include <errno.h> +#include <libpeas/peas-extension-base.h> +#include <libpeas/peas-object-module.h> +#include <libpeas/peas-activatable.h> + +#include "totem-plugin.h" +#include "totem-interface.h" +#include "backend/bacon-video-widget.h" + +#define TOTEM_TYPE_ROTATION_PLUGIN (totem_rotation_plugin_get_type ()) +#define TOTEM_ROTATION_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TOTEM_TYPE_ROTATION_PLUGIN, TotemRotationPlugin)) +#define TOTEM_ROTATION_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TOTEM_TYPE_ROTATION_PLUGIN, TotemRotationPluginClass)) +#define TOTEM_IS_ROTATION_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TOTEM_TYPE_ROTATION_PLUGIN)) +#define TOTEM_IS_ROTATION_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TOTEM_TYPE_ROTATION_PLUGIN)) +#define TOTEM_ROTATION_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TOTEM_TYPE_ROTATION_PLUGIN, TotemRotationPluginClass)) + +#define GIO_ROTATION_FILE_ATTRIBUTE "metadata::totem::rotation" +#define STATE_COUNT 4 + +typedef struct { + TotemObject *totem; + GtkWidget *bvw; + + GCancellable *cancellable; + GSimpleAction *rotate_left_action; + GSimpleAction *rotate_right_action; +} TotemRotationPluginPrivate; + +TOTEM_PLUGIN_REGISTER(TOTEM_TYPE_ROTATION_PLUGIN, TotemRotationPlugin, totem_rotation_plugin) + +static void +store_state_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + if (!g_file_set_attributes_finish (G_FILE (source_object), res, NULL, &error)) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_warning ("Could not store file attribute: %s", error->message); + } + g_error_free (error); + } +} + +static void +store_state (TotemRotationPlugin *pi) +{ + TotemRotationPluginPrivate *priv = pi->priv; + BvwRotation rotation; + char *rotation_s; + GFileInfo *info; + char *mrl; + GFile *file; + + rotation = bacon_video_widget_get_rotation (BACON_VIDEO_WIDGET (priv->bvw)); + rotation_s = g_strdup_printf ("%u", rotation); + info = g_file_info_new (); + g_file_info_set_attribute_string (info, GIO_ROTATION_FILE_ATTRIBUTE, rotation_s); + g_free (rotation_s); + + mrl = totem_object_get_current_mrl (priv->totem); + file = g_file_new_for_uri (mrl); + g_free (mrl); + g_file_set_attributes_async (file, + info, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + priv->cancellable, + store_state_cb, + pi); + g_object_unref (file); +} + +static void +restore_state_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + TotemRotationPlugin *pi; + GError *error = NULL; + GFileInfo *info; + const char *rotation_s; + BvwRotation rotation; + + info = g_file_query_info_finish (G_FILE (source_object), res, &error); + if (info == NULL) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_warning ("Could not query file attribute: %s", error->message); + } + g_error_free (error); + return; + } + + pi = user_data; + + rotation_s = g_file_info_get_attribute_string (info, GIO_ROTATION_FILE_ATTRIBUTE); + if (!rotation_s) + goto out; + + rotation = atoi (rotation_s); + bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (pi->priv->bvw), rotation); + +out: + g_object_unref (info); +} + +static void +restore_state (TotemRotationPlugin *pi) +{ + TotemRotationPluginPrivate *priv = pi->priv; + char *mrl; + GFile *file; + + mrl = totem_object_get_current_mrl (priv->totem); + file = g_file_new_for_uri (mrl); + g_free (mrl); + + g_file_query_info_async (file, + GIO_ROTATION_FILE_ATTRIBUTE, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + priv->cancellable, + restore_state_cb, + pi); + g_object_unref (file); +} + +static void +update_state (TotemRotationPlugin *pi, + const char *mrl) +{ + TotemRotationPluginPrivate *priv = pi->priv; + + if (mrl == NULL) { + bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (priv->bvw), + BVW_ROTATION_R_ZERO); + g_simple_action_set_enabled (priv->rotate_left_action, FALSE); + g_simple_action_set_enabled (priv->rotate_right_action, FALSE); + } else { + g_simple_action_set_enabled (priv->rotate_left_action, TRUE); + g_simple_action_set_enabled (priv->rotate_right_action, TRUE); + restore_state (pi); + } +} + +static void +cb_rotate_left (GSimpleAction *simple, + GVariant *parameter, + gpointer user_data) +{ + TotemRotationPlugin *pi = user_data; + TotemRotationPluginPrivate *priv = pi->priv; + int state; + + state = (bacon_video_widget_get_rotation (BACON_VIDEO_WIDGET (priv->bvw)) - 1) % STATE_COUNT; + bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (priv->bvw), state); + store_state (pi); +} + +static void +cb_rotate_right (GSimpleAction *simple, + GVariant *parameter, + gpointer user_data) +{ + TotemRotationPlugin *pi = user_data; + TotemRotationPluginPrivate *priv = pi->priv; + int state; + + state = (bacon_video_widget_get_rotation (BACON_VIDEO_WIDGET (priv->bvw)) + 1) % STATE_COUNT; + bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (priv->bvw), state); + store_state (pi); +} + +static void +totem_rotation_file_closed (TotemObject *totem, + TotemRotationPlugin *pi) +{ + update_state (pi, NULL); +} + +static void +totem_rotation_file_opened (TotemObject *totem, + const char *mrl, + TotemRotationPlugin *pi) +{ + update_state (pi, mrl); +} + +static void +impl_activate (PeasActivatable *plugin) +{ + TotemRotationPlugin *pi = TOTEM_ROTATION_PLUGIN (plugin); + TotemRotationPluginPrivate *priv = pi->priv; + GMenu *menu; + GMenuItem *item; + char *mrl; + + priv->totem = g_object_get_data (G_OBJECT (plugin), "object"); + priv->bvw = totem_object_get_video_widget (priv->totem); + priv->cancellable = g_cancellable_new (); + + g_signal_connect (priv->totem, + "file-opened", + G_CALLBACK (totem_rotation_file_opened), + plugin); + g_signal_connect (priv->totem, + "file-closed", + G_CALLBACK (totem_rotation_file_closed), + plugin); + + /* add UI */ + menu = totem_object_get_menu_section (priv->totem, "rotation-placeholder"); + + priv->rotate_left_action = g_simple_action_new ("rotate-left", NULL); + g_signal_connect (G_OBJECT (priv->rotate_left_action), "activate", + G_CALLBACK (cb_rotate_left), pi); + g_action_map_add_action (G_ACTION_MAP (priv->totem), + G_ACTION (priv->rotate_left_action)); + + priv->rotate_right_action = g_simple_action_new ("rotate-right", NULL); + g_signal_connect (G_OBJECT (priv->rotate_right_action), "activate", + G_CALLBACK (cb_rotate_right), pi); + g_action_map_add_action (G_ACTION_MAP (priv->totem), + G_ACTION (priv->rotate_right_action)); + + item = g_menu_item_new (_("_Rotate ↷"), "app.rotate-right"); + g_menu_item_set_attribute (item, "accel", "s", "<Primary>R"); + g_menu_append_item (G_MENU (menu), item); + + item = g_menu_item_new (_("Rotate ↶"), "app.rotate-left"); + g_menu_item_set_attribute (item, "accel", "s", "<Primary><Shift>R"); + g_menu_append_item (G_MENU (menu), item); + + mrl = totem_object_get_current_mrl (priv->totem); + update_state (pi, mrl); + g_free (mrl); +} + +static void +impl_deactivate (PeasActivatable *plugin) +{ + TotemRotationPlugin *pi = TOTEM_ROTATION_PLUGIN (plugin); + TotemRotationPluginPrivate *priv = pi->priv; + + if (priv->cancellable != NULL) { + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + } + + g_signal_handlers_disconnect_by_func (priv->totem, totem_rotation_file_opened, plugin); + g_signal_handlers_disconnect_by_func (priv->totem, totem_rotation_file_closed, plugin); + + totem_object_empty_menu_section (priv->totem, "rotation-placeholder"); + g_action_map_remove_action (G_ACTION_MAP (priv->totem), "rotate-left"); + g_action_map_remove_action (G_ACTION_MAP (priv->totem), "rotate-right"); + + bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (priv->bvw), + BVW_ROTATION_R_ZERO); + + priv->totem = NULL; + priv->bvw = NULL; +} |