[gnome-shell] Expose screencast functionality via DBus



commit 24c530611f4ece4d74da2f8028c350e34ef011ef
Author: Florian Müllner <fmuellner gnome org>
Date:   Mon May 6 18:50:31 2013 +0200

    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(+), 0 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index f555d9a..ece7925 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 0000000..6be4010
--- /dev/null
+++ b/data/org.gnome.Shell.Screencast.xml
@@ -0,0 +1,96 @@
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+
+  <!--
+      org.gnome.Shell.Screencast:
+      @short_description: Screencast interface
+
+      The interface used to record screen contents.
+  -->
+  <interface name="org.gnome.Shell.Screencast">
+
+    <!--
+        Screencast:
+        @file_template: the template for the filename to use
+        @options: a dictionary of optional parameters
+        @success: whether the screencast was started successfully
+        @filename_used: the file where the screencast is being saved
+
+        Records a screencast of the whole screen and saves it
+        (by default) as webm video under a filename derived from
+        @file_template. The template is either a relative or absolute
+        filename which may contain some escape sequences - %d and %t
+        will be replaced by the start date and time of the recording.
+        If a relative name is used, the screencast will be saved in the
+        $XDG_VIDEOS_DIR if it exists, or the home directory otherwise.
+        The actual filename of the saved video is returned in @filename_used.
+        The set of optional parameters in @options currently consists of:
+            'draw-cursor'(b): whether the cursor should be included in the
+                              recording (true)
+            'framerate'(i): the number of frames per second that should be
+                            recorded if possible (30)
+            'pipeline'(s): the GStreamer pipeline used to encode recordings
+                           in gst-launch format; if not specified, the
+                           recorder will produce vp8 (webm) video (unset)
+    -->
+    <method name="Screencast">
+      <arg type="s" direction="in" name="file_template"/>
+      <arg type="a{sv}" direction="in" name="options"/>
+      <arg type="b" direction="in" name="flash"/>
+      <arg type="b" direction="out" name="success"/>
+      <arg type="s" direction="out" name="filename_used"/>
+    </method>
+
+    <!--
+        ScreencastArea:
+        @x: the X coordinate of the area to capture
+        @y: the Y coordinate of the area to capture
+        @width: the width of the area to capture
+        @height: the height of the area to capture
+        @file_template: the template for the filename to use
+        @options: a dictionary of optional parameters
+        @success: whether the screencast was started successfully
+        @filename_used: the file where the screencast is being saved
+
+        Records a screencast of the passed in area and saves it
+        (by default) as webm video under a filename derived from
+        @file_template. The template is either a relative or absolute
+        filename which may contain some escape sequences - %d and %t
+        will be replaced by the start date and time of the recording.
+        If a relative name is used, the screencast will be saved in the
+        $XDG_VIDEOS_DIR if it exists, or the home directory otherwise.
+        The actual filename of the saved video is returned in @filename_used.
+        The set of optional parameters in @options currently consists of:
+            'draw-cursor'(b): whether the cursor should be included in the
+                              recording (true)
+            'framerate'(i): the number of frames per second that should be
+                            recorded if possible (30)
+            'pipeline'(s): the GStreamer pipeline used to encode recordings
+                           in gst-launch format; if not specified, the
+                           recorder will produce vp8 (webm) video (unset)
+    -->
+    <method name="ScreencastArea">
+      <arg type="i" direction="in" name="x"/>
+      <arg type="i" direction="in" name="y"/>
+      <arg type="i" direction="in" name="width"/>
+      <arg type="i" direction="in" name="height"/>
+      <arg type="s" direction="in" name="file_template"/>
+      <arg type="a{sv}" direction="in" name="options"/>
+      <arg type="b" direction="out" name="success"/>
+      <arg type="s" direction="out" name="filename_used"/>
+    </method>
+
+    <!--
+        StopScreencast:
+        @success: whether stopping the recording was successful
+
+        Stop the recording started by either Screencast or ScreencastArea.
+    -->
+    <method name="StopScreencasta">
+      <arg type="b" direction="out" name="success"/>
+    </method>
+
+  </interface>
+</node>
diff --git a/js/Makefile.am b/js/Makefile.am
index 62c8323..e8dd927 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 0000000..642d40a
--- /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 = <interface name="org.gnome.Shell.Screencast">
+<method name="Screencast">
+    <arg type="s" direction="in" name="file_template"/>
+    <arg type="a{sv}" direction="in" name="options"/>
+    <arg type="b" direction="out" name="success"/>
+    <arg type="s" direction="out" name="filename_used"/>
+</method>
+<method name="ScreencastArea">
+    <arg type="i" direction="in" name="x"/>
+    <arg type="i" direction="in" name="y"/>
+    <arg type="i" direction="in" name="width"/>
+    <arg type="i" direction="in" name="height"/>
+    <arg type="s" direction="in" name="file_template"/>
+    <arg type="a{sv}" direction="in" name="options"/>
+    <arg type="b" direction="out" name="success"/>
+    <arg type="s" direction="out" name="filename_used"/>
+</method>
+<method name="StopScreencast">
+    <arg type="b" direction="out" name="success"/>
+</method>
+</interface>;
+
+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 12e4b84..952613b 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 = <interface name="org.gnome.Shell">
@@ -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();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]