| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /*
- Copyright (C) 2013 Borsato Ivano
- The JavaScript code in this page is free software: you can
- redistribute it and/or modify it under the terms of the GNU
- General Public License (GNU GPL) as published by the Free Software
- Foundation, either version 3 of the License, or (at your option)
- any later version. The code is distributed WITHOUT ANY WARRANTY;
- without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
- */
- 'use strict';
- import GObject from 'gi://GObject';
- import Gio from 'gi://Gio';
- import GLib from 'gi://GLib';
- import {loadInterfaceXML} from 'resource:///org/gnome/shell/misc/dbusUtils.js';
- const ScreencastIface = loadInterfaceXML('org.gnome.Shell.Screencast');
- import * as Lib from './convenience.js';
- import * as Settings from './settings.js';
- import * as Selection from './selection.js';
- import * as UtilGSP from './utilgsp.js';
- import * as Ext from './extension.js';
- /**
- * @type {CaptureVideo}
- */
- export const CaptureVideo = GObject.registerClass({
- GTypeName: 'EasyScreenCast_CaptureVideo',
- }, class CaptureVideo extends GObject.Object {
- /**
- * Create a video recorder
- */
- constructor() {
- super();
- Lib.TalkativeLog('-&-init recorder');
- this.AreaSelected = null;
- // connect to d-bus service
- const ScreenCastProxy = Gio.DBusProxy.makeProxyWrapper(ScreencastIface);
- this._screenCastService = new ScreenCastProxy(
- Gio.DBus.session,
- 'org.gnome.Shell.Screencast',
- '/org/gnome/Shell/Screencast',
- (proxy, error) => {
- if (error)
- Lib.TalkativeLog(`-&-ERROR(d-bus proxy connected) - ${error.message}`);
- else
- Lib.TalkativeLog('-&-d-bus proxy connected');
- }
- );
- }
- /**
- * start recording
- */
- start() {
- Lib.TalkativeLog('-&-start video recording');
- this.recordingActive = false;
- let fileExt = UtilGSP.getFileExtension(
- Ext.Indicator.getSettings().getOption('i', Settings.FILE_CONTAINER_SETTING_KEY)
- );
- // prepare variable for screencast
- let fileRec = Ext.Indicator.getSettings().getOption('s', Settings.FILE_NAME_SETTING_KEY);
- let folderRec = '';
- if (Ext.Indicator.getSettings().getOption('s', Settings.FILE_FOLDER_SETTING_KEY) !== '')
- folderRec = Ext.Indicator.getSettings().getOption('s', Settings.FILE_FOLDER_SETTING_KEY);
- let pipelineRec = '';
- if (Ext.Indicator.getSettings().getOption('b', Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY)) {
- pipelineRec = Ext.Indicator.getSettings().getOption(
- 's',
- Settings.PIPELINE_REC_SETTING_KEY
- );
- } else {
- // compose GSP
- pipelineRec = UtilGSP.composeGSP(Ext.Indicator.getSettings(), Ext.Indicator.CtrlAudio);
- }
- Lib.TalkativeLog(`-&-file template : ${fileRec}`);
- fileRec = this._generateFileName(fileRec);
- Lib.TalkativeLog(`-&-file final : ${fileRec}`);
- const completeFileRecPath = folderRec !== ''
- ? `${folderRec}/${fileRec}`
- : fileRec;
- Lib.TalkativeLog(`-&-file rec path complete : ${completeFileRecPath}${fileExt}`);
- // prefix with a videoconvert element
- // see DEFAULT_PIPELINE in https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/dbusServices/screencast/screencastService.js#L26
- // this videoconvert element was added always previously (< Gnome 40) and needs to be added now explicitly
- // https://gitlab.gnome.org/GNOME/gnome-shell/-/commit/51bf7ec17617a9ed056dd563afdb98e17da07373
- pipelineRec = `videoconvert chroma-mode=GST_VIDEO_CHROMA_MODE_NONE dither=GST_VIDEO_DITHER_NONE matrix-mode=GST_VIDEO_MATRIX_MODE_OUTPUT_ONLY n-threads=%T ! queue ! ${pipelineRec}`;
- Lib.TalkativeLog(`-&-pipeline : pipeline: ${pipelineRec}`);
- var optionsRec = {
- 'draw-cursor': new GLib.Variant(
- 'b',
- Ext.Indicator.getSettings().getOption('b', Settings.DRAW_CURSOR_SETTING_KEY)
- ),
- framerate: new GLib.Variant(
- 'i',
- Ext.Indicator.getSettings().getOption('i', Settings.FPS_SETTING_KEY)
- ),
- pipeline: new GLib.Variant('s', pipelineRec),
- };
- if (Ext.Indicator.getSettings().getOption('i', Settings.AREA_SCREEN_SETTING_KEY) === 0) {
- this._screenCastService.ScreencastRemote(
- completeFileRecPath,
- optionsRec,
- (result, error) => {
- if (error) {
- Lib.TalkativeLog(`-&-ERROR(screencast execute) - ${error.message}`);
- this.stop();
- Ext.Indicator.doRecResult(false);
- } else {
- Lib.TalkativeLog(`-&-screencast execute - ${result[0]} - ${result[1]}`);
- let resultingFilePath = result[1];
- if (resultingFilePath.endsWith('.undefined')) {
- resultingFilePath = resultingFilePath.substring(0, resultingFilePath.length - '.undefined'.length);
- resultingFilePath = `${resultingFilePath}${fileExt}`;
- }
- this._originalFilePath = result[1];
- this._filePathWithExtension = resultingFilePath;
- Ext.Indicator.doRecResult(result[0], resultingFilePath);
- }
- }
- );
- } else {
- this._screenCastService.ScreencastAreaRemote(
- Ext.Indicator.getSettings().getOption('i', Settings.X_POS_SETTING_KEY),
- Ext.Indicator.getSettings().getOption('i', Settings.Y_POS_SETTING_KEY),
- Ext.Indicator.getSettings().getOption('i', Settings.WIDTH_SETTING_KEY),
- Ext.Indicator.getSettings().getOption('i', Settings.HEIGHT_SETTING_KEY),
- completeFileRecPath,
- optionsRec,
- (result, error) => {
- if (error) {
- Lib.TalkativeLog(`-&-ERROR(screencast execute) - ${error.message}`);
- this.stop();
- Ext.Indicator.doRecResult(false);
- } else {
- Lib.TalkativeLog(`-&-screencast execute - ${result[0]} - ${result[1]}`);
- // draw area recording
- if (Ext.Indicator.getSettings().getOption('b', Settings.SHOW_AREA_REC_SETTING_KEY))
- this.AreaSelected = new Selection.AreaRecording();
- let resultingFilePath = result[1];
- if (resultingFilePath.endsWith('.undefined')) {
- resultingFilePath = resultingFilePath.substring(0, resultingFilePath.length - '.undefined'.length);
- resultingFilePath = `${resultingFilePath}${fileExt}`;
- }
- this._originalFilePath = result[1];
- this._filePathWithExtension = resultingFilePath;
- Ext.Indicator.doRecResult(result[0], resultingFilePath);
- }
- }
- );
- }
- }
- /**
- * Stop recording
- *
- * @returns {boolean}
- */
- stop() {
- Lib.TalkativeLog('-&-stop video recording');
- this._screenCastService.StopScreencastRemote((result, error) => {
- if (error) {
- Lib.TalkativeLog(`-&-ERROR(screencast stop) - ${error.message}`);
- return false;
- } else {
- Lib.TalkativeLog(`-&-screencast stop - ${result[0]}`);
- // rename the file...
- Lib.TalkativeLog(`-&-screencast: rename ${this._originalFilePath} to ${this._filePathWithExtension}`);
- const sourceFile = Gio.File.new_for_path(this._originalFilePath);
- const destFile = Gio.File.new_for_path(this._filePathWithExtension);
- sourceFile.move(destFile, 0, null, null);
- }
- // clear area recording
- if (this.AreaSelected !== null && this.AreaSelected.isVisible())
- this.AreaSelected.clearArea();
- return true;
- });
- }
- // without file extension
- _generateFileName(template) {
- template = template.replaceAll('%d', '%0x').replaceAll('%t', '%0X');
- const datetime = GLib.DateTime.new_now_local();
- let result = datetime.format(template);
- result = result.replaceAll(' ', '_'); // remove white space
- result = result.replaceAll('/', '_'); // remove path separators
- return result;
- }
- });
|