From dfb44aa51d989558d8a607d9e16c7a85f4169653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 6 May 2013 18:50:31 +0200 Subject: [PATCH] Expose screencast functionality via DBus Like screenshots, the screen recorder can be a useful tool in other cases than being triggered by a keyboard shortcut. To account for that, export a Screencast DBus API similar to the existing Screenshot interface. https://bugzilla.gnome.org/show_bug.cgi?id=696247 --- data/Makefile.am | 1 + data/org.gnome.Shell.Screencast.xml | 96 +++++++++++++++++++ js/Makefile.am | 1 + js/ui/screencast.js | 138 ++++++++++++++++++++++++++++ js/ui/shellDBus.js | 2 + 5 files changed, 238 insertions(+) create mode 100644 data/org.gnome.Shell.Screencast.xml create mode 100644 js/ui/screencast.js diff --git a/data/Makefile.am b/data/Makefile.am index f555d9a84..ece792553 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -15,6 +15,7 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop introspectiondir = $(datadir)/dbus-1/interfaces introspection_DATA = \ + org.gnome.Shell.Screencast.xml \ org.gnome.Shell.Screenshot.xml \ org.gnome.ShellSearchProvider.xml \ org.gnome.ShellSearchProvider2.xml diff --git a/data/org.gnome.Shell.Screencast.xml b/data/org.gnome.Shell.Screencast.xml new file mode 100644 index 000000000..6be4010dc --- /dev/null +++ b/data/org.gnome.Shell.Screencast.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/Makefile.am b/js/Makefile.am index 62c8323ad..e8dd927dc 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -78,6 +78,7 @@ nobase_dist_js_DATA = \ ui/popupMenu.js \ ui/remoteSearch.js \ ui/runDialog.js \ + ui/screencast.js \ ui/screenshot.js \ ui/screenShield.js \ ui/scripting.js \ diff --git a/js/ui/screencast.js b/js/ui/screencast.js new file mode 100644 index 000000000..642d40ac6 --- /dev/null +++ b/js/ui/screencast.js @@ -0,0 +1,138 @@ +// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- + +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; +const Lang = imports.lang; +const Shell = imports.gi.Shell; + +const Hash = imports.misc.hash; +const Main = imports.ui.main; + +const ScreencastIface = + + + + + + + + + + + + + + + + + + + +; + +const ScreencastService = new Lang.Class({ + Name: 'ScreencastService', + + _init: function() { + this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreencastIface, this); + this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screencast'); + + Gio.DBus.session.own_name('org.gnome.Shell.Screencast', Gio.BusNameOwnerFlags.REPLACE, null, null); + + this._recorders = new Hash.Map(); + + Main.sessionMode.connect('updated', + Lang.bind(this, this._sessionModeChanged)); + }, + + _ensureRecorderForSender: function(sender) { + let recorder = this._recorders.get(sender); + if (!recorder) { + recorder = new Shell.Recorder({ stage: global.stage }); + recorder._watchNameId = + Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null, + Lang.bind(this, this._onNameVanished)); + this._recorders.set(sender, recorder); + } + return recorder; + }, + + _sessionModeChanged: function() { + if (Main.sessionMode.allowScreencast) + return; + + for (let sender in this._recorders.keys()) + this._recorders.delete(sender); + }, + + _onNameVanished: function(connection, name) { + this._stopRecordingForSender(name); + }, + + _stopRecordingForSender: function(sender) { + let recorder = this._recorders.get(sender); + if (!recorder) + return false; + + Gio.bus_unwatch_name(recorder._watchNameId); + recorder.close(); + this._recorders.delete(sender); + + return true; + }, + + _applyOptionalParameters: function(recorder, options) { + for (let option in options) + options[option] = options[option].deep_unpack(); + + if (options['pipeline']) + recorder.set_pipeline(options['pipeline']); + if (options['framerate']) + recorder.set_framerate(options['framerate']); + if (options['draw-cursor']) + recorder.set_draw_cursor(options['draw-cursor']); + }, + + ScreencastAsync: function(params, invocation) { + let returnValue = [false, '']; + if (!Main.sessionMode.allowScreencast) + invocation.return_value(GLib.Variant.new('(bs)', returnValue)); + + let sender = invocation.get_sender(); + let recorder = this._ensureRecorderForSender(sender); + if (!recorder.is_recording()) { + let [fileTemplate, options] = params; + + recorder.set_file_template(fileTemplate); + this._applyOptionalParameters(recorder, options); + returnValue = recorder.record(); + } + + invocation.return_value(GLib.Variant.new('(bs)', returnValue)); + }, + + ScreencastAreaAsync: function(params, invocation) { + let returnValue = [false, '']; + if (!Main.sessionMode.allowScreencast) + invocation.return_value(GLib.Variant.new('(bs)', returnValue)); + + let sender = invocation.get_sender(); + let recorder = this._ensureRecorderForSender(sender); + + if (!recorder.is_recording()) { + let [x, y, width, height, fileTemplate, options] = params; + + recorder.set_file_template(fileTemplate); + recorder.set_area(x, y, width, height); + this._applyOptionalParameters(recorder, options); + returnValue = recorder.record(); + } + + invocation.return_value(GLib.Variant.new('(bs)', returnValue)); + }, + + StopScreencastAsync: function(params, invocation) { + let success = this._stopRecordingForSender(invocation.get_sender()); + invocation.return_value(GLib.Variant.new('(b)', [success])); + } +}); diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index 12e4b844b..952613b31 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -12,6 +12,7 @@ const ExtensionDownloader = imports.ui.extensionDownloader; const ExtensionUtils = imports.misc.extensionUtils; const Hash = imports.misc.hash; const Main = imports.ui.main; +const Screencast = imports.ui.screencast; const Screenshot = imports.ui.screenshot; const GnomeShellIface = @@ -70,6 +71,7 @@ const GnomeShell = new Lang.Class({ this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); this._extensionsService = new GnomeShellExtensions(); + this._screencastService = new Screencast.ScreencastService(); this._screenshotService = new Screenshot.ScreenshotService(); this._grabbedAccelerators = new Hash.Map();