2013-05-06 16:50:31 +00:00
|
|
|
// -*- 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;
|
2013-07-17 19:26:06 +00:00
|
|
|
const Signals = imports.signals;
|
2013-05-06 16:50:31 +00:00
|
|
|
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
|
2013-10-24 21:51:58 +00:00
|
|
|
const ScreencastIface = '<node> \
|
|
|
|
<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> \
|
|
|
|
</node>';
|
2013-05-06 16:50:31 +00:00
|
|
|
|
2017-07-18 17:41:25 +00:00
|
|
|
var ScreencastService = new Lang.Class({
|
2013-05-06 16:50:31 +00:00
|
|
|
Name: 'ScreencastService',
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_init() {
|
2013-05-06 16:50:31 +00:00
|
|
|
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);
|
|
|
|
|
2014-01-14 22:49:47 +00:00
|
|
|
this._recorders = new Map();
|
2013-05-06 16:50:31 +00:00
|
|
|
|
2014-10-03 14:40:49 +00:00
|
|
|
this._lockdownSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.lockdown' });
|
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
2013-05-06 16:50:31 +00:00
|
|
|
},
|
|
|
|
|
2013-07-17 19:26:06 +00:00
|
|
|
get isRecording() {
|
2014-01-14 22:49:47 +00:00
|
|
|
return this._recorders.size > 0;
|
2013-07-17 19:26:06 +00:00
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_ensureRecorderForSender(sender) {
|
2013-05-06 16:50:31 +00:00
|
|
|
let recorder = this._recorders.get(sender);
|
|
|
|
if (!recorder) {
|
2013-08-14 08:34:58 +00:00
|
|
|
recorder = new Shell.Recorder({ stage: global.stage,
|
|
|
|
screen: global.screen });
|
2013-05-06 16:50:31 +00:00
|
|
|
recorder._watchNameId =
|
|
|
|
Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
|
2017-12-02 00:27:35 +00:00
|
|
|
this._onNameVanished.bind(this));
|
2013-05-06 16:50:31 +00:00
|
|
|
this._recorders.set(sender, recorder);
|
2013-07-17 19:26:06 +00:00
|
|
|
this.emit('updated');
|
2013-05-06 16:50:31 +00:00
|
|
|
}
|
|
|
|
return recorder;
|
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_sessionUpdated() {
|
2013-05-06 16:50:31 +00:00
|
|
|
if (Main.sessionMode.allowScreencast)
|
|
|
|
return;
|
|
|
|
|
2014-10-03 12:46:36 +00:00
|
|
|
for (let sender of this._recorders.keys())
|
|
|
|
this._stopRecordingForSender(sender);
|
2013-05-06 16:50:31 +00:00
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onNameVanished(connection, name) {
|
2013-05-06 16:50:31 +00:00
|
|
|
this._stopRecordingForSender(name);
|
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_stopRecordingForSender(sender) {
|
2013-05-06 16:50:31 +00:00
|
|
|
let recorder = this._recorders.get(sender);
|
|
|
|
if (!recorder)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Gio.bus_unwatch_name(recorder._watchNameId);
|
|
|
|
recorder.close();
|
|
|
|
this._recorders.delete(sender);
|
2013-07-17 19:26:06 +00:00
|
|
|
this.emit('updated');
|
2013-05-06 16:50:31 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_applyOptionalParameters(recorder, options) {
|
2013-05-06 16:50:31 +00:00
|
|
|
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']);
|
2015-02-16 15:56:05 +00:00
|
|
|
if ('draw-cursor' in options)
|
2013-05-06 16:50:31 +00:00
|
|
|
recorder.set_draw_cursor(options['draw-cursor']);
|
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
ScreencastAsync(params, invocation) {
|
2013-05-06 16:50:31 +00:00
|
|
|
let returnValue = [false, ''];
|
2014-10-03 14:40:49 +00:00
|
|
|
if (!Main.sessionMode.allowScreencast ||
|
|
|
|
this._lockdownSettings.get_boolean('disable-save-to-disk')) {
|
2013-05-06 16:50:31 +00:00
|
|
|
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
2013-11-04 13:06:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-05-06 16:50:31 +00:00
|
|
|
|
|
|
|
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);
|
2013-05-22 14:42:00 +00:00
|
|
|
let [success, fileName] = recorder.record();
|
|
|
|
returnValue = [success, fileName ? fileName : ''];
|
2014-10-03 14:49:21 +00:00
|
|
|
if (!success)
|
|
|
|
this._stopRecordingForSender(sender);
|
2013-05-06 16:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
ScreencastAreaAsync(params, invocation) {
|
2013-05-06 16:50:31 +00:00
|
|
|
let returnValue = [false, ''];
|
2014-10-03 14:40:49 +00:00
|
|
|
if (!Main.sessionMode.allowScreencast ||
|
|
|
|
this._lockdownSettings.get_boolean('disable-save-to-disk')) {
|
2013-05-06 16:50:31 +00:00
|
|
|
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
2013-11-04 13:06:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-05-06 16:50:31 +00:00
|
|
|
|
|
|
|
let sender = invocation.get_sender();
|
|
|
|
let recorder = this._ensureRecorderForSender(sender);
|
|
|
|
|
|
|
|
if (!recorder.is_recording()) {
|
|
|
|
let [x, y, width, height, fileTemplate, options] = params;
|
|
|
|
|
2013-11-04 13:09:19 +00:00
|
|
|
if (x < 0 || y < 0 ||
|
|
|
|
width <= 0 || height <= 0 ||
|
|
|
|
x + width > global.screen_width ||
|
|
|
|
y + height > global.screen_height) {
|
|
|
|
invocation.return_error_literal(Gio.IOErrorEnum,
|
|
|
|
Gio.IOErrorEnum.CANCELLED,
|
|
|
|
"Invalid params");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-06 16:50:31 +00:00
|
|
|
recorder.set_file_template(fileTemplate);
|
|
|
|
recorder.set_area(x, y, width, height);
|
|
|
|
this._applyOptionalParameters(recorder, options);
|
2013-05-22 14:42:00 +00:00
|
|
|
let [success, fileName] = recorder.record();
|
|
|
|
returnValue = [success, fileName ? fileName : ''];
|
2014-10-03 14:49:21 +00:00
|
|
|
if (!success)
|
|
|
|
this._stopRecordingForSender(sender);
|
2013-05-06 16:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
|
|
|
},
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
StopScreencastAsync(params, invocation) {
|
2013-05-06 16:50:31 +00:00
|
|
|
let success = this._stopRecordingForSender(invocation.get_sender());
|
|
|
|
invocation.return_value(GLib.Variant.new('(b)', [success]));
|
|
|
|
}
|
|
|
|
});
|
2013-07-17 19:26:06 +00:00
|
|
|
Signals.addSignalMethods(ScreencastService.prototype);
|