| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034 |
- /*
- 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 St from 'gi://St';
- import Meta from 'gi://Meta';
- import Shell from 'gi://Shell';
- // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panelMenu.js
- import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
- import Clutter from 'gi://Clutter';
- import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
- import * as Slider from 'resource:///org/gnome/shell/ui/slider.js';
- import * as Main from 'resource:///org/gnome/shell/ui/main.js';
- import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
- import * as Lib from './convenience.js';
- import * as Settings from './settings.js';
- import * as Time from './timer.js';
- import * as UtilRecorder from './utilrecorder.js';
- import * as UtilAudio from './utilaudio.js';
- import * as UtilWebcam from './utilwebcam.js';
- import * as UtilNotify from './utilnotify.js';
- import * as Selection from './selection.js';
- import * as UtilExeCmd from './utilexecmd.js';
- var Indicator;
- let timerD = null;
- let timerC = null;
- let isActive = false;
- let pathFile = '';
- let keybindingConfigured = false;
- /**
- * @type {EasyScreenCastIndicator}
- */
- const EasyScreenCastIndicator = GObject.registerClass({
- GTypeName: 'EasyScreenCast_Indicator',
- }, class EasyScreenCastIndicator extends PanelMenu.Button {
- constructor(extension) {
- super(null, 'EasyScreenCast_Indicator');
- this._extension = extension;
- this._settings = new Settings.Settings(this._extension.getSettings());
- Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY));
- this._settings._settings.connect(
- `changed::${Settings.VERBOSE_DEBUG_SETTING_KEY}`,
- () => {
- Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY));
- }
- );
- this.CtrlAudio = new UtilAudio.MixerAudio();
- this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam'));
- this.CtrlNotify = new UtilNotify.NotifyManager();
- this.CtrlExe = new UtilExeCmd.ExecuteStuff(this);
- // load indicator icons
- this._icons = {
- on: Lib.loadIcon(this._extension.dir, 'icon_recording.svg'),
- onSel: Lib.loadIcon(this._extension.dir, 'icon_recordingSel.svg'),
- off: Lib.loadIcon(this._extension.dir, 'icon_default.svg'),
- offSel: Lib.loadIcon(this._extension.dir, 'icon_defaultSel.svg'),
- };
- // check audio
- if (!this.CtrlAudio.checkAudio()) {
- Lib.TalkativeLog('-*-disable audio recording');
- this._settings.setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, 0);
- this._settings.setOption(
- Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY,
- Settings.getGSPstd(false)
- );
- }
- // add enter/leave/click event
- this.connect('enter_event', () => this.refreshIndicator(true));
- this.connect('leave_event', () => this.refreshIndicator(false));
- this.connect('button_press_event', (actor, event) =>
- this._onButtonPress(actor, event)
- );
- // prepare setting var
- if (this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY) > 0)
- this.isDelayActive = true;
- else
- this.isDelayActive = false;
- // Add the title bar icon and label for time display
- this.indicatorBox = new St.BoxLayout();
- this.indicatorIcon = new St.Icon({
- gicon: this._icons.off,
- icon_size: 16,
- });
- this.timeLabel = new St.Label({
- text: '',
- style_class: 'time-label',
- y_expand: true,
- y_align: Clutter.ActorAlign.CENTER,
- });
- this.indicatorBox.add_child(this.timeLabel);
- this.indicatorBox.add_child(this.indicatorIcon);
- // init var
- this.recorder = new UtilRecorder.CaptureVideo();
- this.AreaSelected = null;
- this.TimeSlider = null;
- this._initMainMenu();
- }
- /**
- * @private
- */
- _initMainMenu() {
- this._addStartStopMenuEntry();
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this.sub_menu_audio_recording = new PopupMenu.PopupSubMenuMenuItem(_('No audio source'), true);
- this.sub_menu_audio_recording.icon.icon_name = 'audio-input-microphone-symbolic';
- this.menu.addMenuItem(this.sub_menu_audio_recording);
- this._addAudioRecordingSubMenu();
- // add sub menu webcam recording
- this._addSubMenuWebCam();
- this._addAreaRecordingSubMenu();
- this._addRecordingDelaySubMenu();
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this.menu_item_options = new PopupMenu.PopupMenuItem(_('Options'));
- this.menu_item_options.actor.insert_child_at_index(
- new St.Icon({
- style_class: 'popup-menu-icon',
- icon_name: 'preferences-other-symbolic',
- }),
- 1
- );
- this.menu.addMenuItem(this.menu_item_options);
- this.menu_item_options.connect('activate', () => this._openExtensionPreferences());
- }
- /**
- * Set a new value for the time label. Integers are
- * converted to seconds, minutes, hours. All other
- * values are converted to strings.
- *
- * @param {string|number} newValue new value of the label. if a number, then it's the seconds passed.
- * @returns {string}
- */
- updateTimeLabel(newValue) {
- /**
- * @param {number} number a number
- */
- function padZeros(number) {
- if (number < 10)
- number = `0${number}`;
- return number.toString();
- }
- if (typeof newValue === 'number') {
- let hours = Math.floor(newValue / 3600);
- newValue -= hours * 3600;
- let minutes = Math.floor(newValue / 60);
- newValue -= minutes * 60;
- newValue = `${padZeros(hours)}:${padZeros(minutes)}:${padZeros(newValue)}`;
- }
- this.timeLabel.set_text(newValue.toString());
- }
- /**
- * Left clicking on the icon toggles the recording
- * options menu. Any other mouse button will start
- * the recording.
- * Some submenus are refreshed to account for new
- * sources.
- *
- * @param {Clutter.Actor} actor the actor
- * @param {Clutter.Event} event a Clutter.Event
- */
- _onButtonPress(actor, event) {
- let button = event.get_button();
- if (button === 1) {
- Lib.TalkativeLog('-*-left click indicator');
- this._setupExtensionMenu();
- } else {
- Lib.TalkativeLog('-*-right click indicator');
- if (this.menu.isOpen)
- this.menu.close();
- this.isShowNotify = this._settings.getOption('b', Settings.SHOW_NOTIFY_ALERT_SETTING_KEY);
- this._doRecording();
- }
- }
- /**
- * Sets up the menu when the user opens it.
- */
- _setupExtensionMenu() {
- this._addAudioRecordingSubMenu();
- this._addWebcamSubMenu();
- }
- /**
- * Sets up all the options for web-cams. Should only run the
- * first time the icon is clicked an the CtrlWebcam is still
- * null.
- */
- _addWebcamSubMenu() {
- if (this.CtrlWebcam === null)
- this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam'));
- // add sub menu webcam recording
- this._populateSubMenuWebcam();
- // start monitoring inputvideo
- this.CtrlWebcam.startMonitor();
- }
- /**
- * Adds individual webcam items to the webcam menu.
- */
- _populateSubMenuWebcam() {
- let arrMI = this._createMIWebCam();
- this.smWebCam.menu.removeAll();
- for (let element in arrMI)
- this.smWebCam.menu.addMenuItem(arrMI[element]);
- let i = this._settings.getOption('i', Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY);
- Lib.TalkativeLog(`-*-populated submenuwebcam. Settings i=${i}`);
- this.smWebCam.label.text = this.WebCamDevice[i];
- }
- /**
- * @private
- */
- _addStartStopMenuEntry() {
- this.imRecordAction = new PopupMenu.PopupBaseMenuItem();
- this.RecordingLabel = new St.Label({
- text: _('Start recording'),
- style_class: 'RecordAction-label',
- content_gravity: Clutter.ContentGravity.CENTER,
- x_expand: true,
- x_align: Clutter.ActorAlign.CENTER,
- });
- this.imRecordAction.actor.add_child(this.RecordingLabel);
- this.imRecordAction.x_expand = true;
- this.imRecordAction.x_fill = true;
- this.imRecordAction.x_align = Clutter.ActorAlign.CENTER;
- this.imRecordAction.connect('activate', () => {
- this.isShowNotify = this._settings.getOption('b', Settings.SHOW_NOTIFY_ALERT_SETTING_KEY);
- this._doRecording();
- });
- this.menu.addMenuItem(this.imRecordAction);
- }
- /**
- * Refreshes the submenu for audio recording sources.
- */
- _addAudioRecordingSubMenu() {
- Lib.TalkativeLog('-*-reset the sub menu audio');
- // remove old menu items
- this.sub_menu_audio_recording.menu.removeAll();
- Lib.TalkativeLog('-*-add new items to sub menu audio');
- var arrMI = this._createMIAudioRec();
- for (var ele in arrMI)
- this.sub_menu_audio_recording.menu.addMenuItem(arrMI[ele]);
- }
- /**
- * @private
- */
- _addSubMenuWebCam() {
- this.smWebCam = new PopupMenu.PopupSubMenuMenuItem('', true);
- this.smWebCam.icon.icon_name = 'camera-web-symbolic';
- this.menu.addMenuItem(this.smWebCam);
- }
- /**
- * @private
- */
- _addAreaRecordingSubMenu() {
- this.sub_menu_area_recording = new PopupMenu.PopupSubMenuMenuItem('', true);
- this.sub_menu_area_recording.icon.icon_name = 'view-fullscreen-symbolic';
- var arrMI = this._createMIAreaRec();
- for (var ele in arrMI)
- this.sub_menu_area_recording.menu.addMenuItem(arrMI[ele]);
- this.sub_menu_area_recording.label.text = this.AreaType[this._settings.getOption('i', Settings.AREA_SCREEN_SETTING_KEY)];
- this.menu.addMenuItem(this.sub_menu_area_recording);
- }
- /**
- * @private
- */
- _addRecordingDelaySubMenu() {
- this.smDelayRec = new PopupMenu.PopupSubMenuMenuItem('', true);
- this.smDelayRec.icon.icon_name = 'alarm-symbolic';
- var arrMI = this._createMIInfoDelayRec();
- for (var ele in arrMI)
- this.smDelayRec.menu.addMenuItem(arrMI[ele]);
- var secDelay = this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY);
- if (secDelay > 0) {
- this.smDelayRec.label.text =
- secDelay + _(' sec. delay before recording');
- } else {
- this.smDelayRec.label.text = _('Start recording immediately');
- }
- this.menu.addMenuItem(this.smDelayRec);
- }
- /**
- * @returns {Array}
- * @private
- */
- _createMIAreaRec() {
- this.AreaType = [
- _('Record all desktop'),
- _('Record a selected monitor'),
- _('Record a selected window'),
- _('Record a selected area'),
- ];
- this.AreaMenuItem = new Array(this.AreaType.length);
- for (var i = 0; i < this.AreaMenuItem.length; i++) {
- this.AreaMenuItem[i] = new PopupMenu.PopupMenuItem(
- this.AreaType[i],
- {
- reactive: true,
- activate: true,
- hover: true,
- can_focus: true,
- }
- );
- (function (areaSetting, arr, item, settings) {
- this.connectMI = function () {
- this.connect('activate', () => {
- Lib.TalkativeLog(`-*-set area recording to ${areaSetting} ${arr[areaSetting]}`);
- settings.setOption(Settings.AREA_SCREEN_SETTING_KEY, areaSetting);
- item.label.text = arr[areaSetting];
- });
- };
- this.connectMI();
- }.call(
- this.AreaMenuItem[i],
- i,
- this.AreaType,
- this.sub_menu_area_recording,
- this._settings
- ));
- }
- return this.AreaMenuItem;
- }
- /**
- * @returns {Array}
- * @private
- */
- _createMIWebCam() {
- this.WebCamDevice = [_('No WebCam recording')];
- // add menu item webcam device from GST
- const devices = this.CtrlWebcam.getDevicesIV();
- this.WebCamDevice.push(...this.CtrlWebcam.getNameDevices());
- Lib.TalkativeLog(`-*-webcam list: ${this.WebCamDevice}`);
- this.AreaMenuItem = new Array(this.WebCamDevice.length);
- for (var i = 0; i < this.AreaMenuItem.length; i++) {
- let devicePath = '';
- // i === 0 is "No Webcam selected"
- if (i > 0) {
- const device = devices[i - 1];
- devicePath = device.get_properties().get_string('device.path');
- Lib.TalkativeLog(`-*-webcam i=${i} devicePath: ${devicePath}`);
- }
- Lib.TalkativeLog(`-*-webcam i=${i} menu-item-text: ${this.WebCamDevice[i]}`);
- this.AreaMenuItem[i] = new PopupMenu.PopupMenuItem(
- this.WebCamDevice[i],
- {
- reactive: true,
- activate: true,
- hover: true,
- can_focus: true,
- }
- );
- (function (index, devPath, arr, item, settings) {
- this.connectMI = function () {
- this.connect('activate', () => {
- Lib.TalkativeLog(`-*-set webcam device to ${index} ${arr[index]} devicePath=${devPath}`);
- settings.setOption(Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY, index);
- settings.setOption(Settings.DEVICE_WEBCAM_SETTING_KEY, devPath);
- item.label.text = arr[index];
- });
- };
- this.connectMI();
- }.call(
- this.AreaMenuItem[i],
- i,
- devicePath,
- this.WebCamDevice,
- this.smWebCam,
- this._settings
- ));
- }
- return this.AreaMenuItem;
- }
- /**
- * @returns {Array}
- * @private
- */
- _createMIAudioRec() {
- // add std menu item
- this.AudioChoice = [
- {
- desc: _('No audio source'),
- name: 'N/A',
- port: 'N/A',
- sortable: true,
- resizeable: true,
- },
- {
- desc: _('Default audio source'),
- name: 'N/A',
- port: 'N/A',
- sortable: true,
- resizeable: true,
- },
- ];
- // add menu item audio source from PA
- var audioList = this.CtrlAudio.getListInputAudio();
- for (var index in audioList)
- this.AudioChoice.push(audioList[index]);
- this.AudioMenuItem = new Array(this.AudioChoice.length);
- for (var i = 0; i < this.AudioChoice.length; i++) {
- // create label menu
- let labelMenu = this.AudioChoice[i].desc;
- if (i >= 2) {
- labelMenu +=
- _('\n - Port: ') +
- this.AudioChoice[i].port +
- _('\n - Name: ') +
- this.AudioChoice[i].name;
- }
- // create submenu
- this.AudioMenuItem[i] = new PopupMenu.PopupMenuItem(labelMenu, {
- reactive: true,
- activate: true,
- hover: true,
- can_focus: true,
- });
- // add icon on submenu
- this.AudioMenuItem[i].actor.insert_child_at_index(
- new St.Icon({
- style_class: 'popup-menu-icon',
- icon_name: 'audio-card-symbolic',
- }),
- 1
- );
- // update choice audio from pref
- if (i === this._settings.getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY)) {
- Lib.TalkativeLog(`-*-get audio choice from pref ${i}`);
- this.sub_menu_audio_recording.label.text = this.AudioChoice[i].desc;
- }
- // add action on menu item
- (function (audioIndex, arr, item, settings) {
- this.connectMI = function () {
- this.connect('activate', () => {
- Lib.TalkativeLog(`-*-set audio choice to ${audioIndex}`);
- settings.setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, audioIndex);
- item.label.text = arr[audioIndex].desc;
- });
- };
- this.connectMI();
- }.call(
- this.AudioMenuItem[i],
- i,
- this.AudioChoice,
- this.sub_menu_audio_recording,
- this._settings
- ));
- }
- return this.AudioMenuItem;
- }
- /**
- * @returns {Array}
- * @private
- */
- _createMIInfoDelayRec() {
- this.DelayTimeTitle = new PopupMenu.PopupMenuItem(_('Delay Time'), {
- reactive: false,
- });
- this.DelayTimeLabel = new St.Label({
- text:
- Math.floor(
- this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY)
- ).toString() + _(' Sec'),
- });
- this.DelayTimeTitle.actor.add_child(this.DelayTimeLabel);
- // TODO this.DelayTimeTitle.align = St.Align.END;
- this.imSliderDelay = new PopupMenu.PopupBaseMenuItem({
- activate: false,
- });
- this.TimeSlider = new Slider.Slider(this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY) / 100);
- this.TimeSlider.x_expand = true;
- this.TimeSlider.y_expand = true;
- this.TimeSlider.connect('notify::value', item => {
- this.DelayTimeLabel.set_text(
- Math.floor(item.value * 100).toString() + _(' Sec')
- );
- });
- this.TimeSlider.connect('drag-end', () => this._onDelayTimeChanged());
- this.TimeSlider.connect('scroll-event', () =>
- this._onDelayTimeChanged()
- );
- this.imSliderDelay.actor.add_child(this.TimeSlider);
- return [this.DelayTimeTitle, this.imSliderDelay];
- }
- /**
- * @private
- */
- _enable() {
- // enable key binding
- this._enableKeybindings();
- // immediately activate/deactive shortcut on settings change
- this._settings._settings.connect(
- `changed::${Settings.ACTIVE_SHORTCUT_SETTING_KEY}`,
- () => {
- if (this._settings.getOption('b', Settings.ACTIVE_SHORTCUT_SETTING_KEY)) {
- Lib.TalkativeLog('-^-shortcut changed - enabling');
- this._enableKeybindings();
- } else {
- Lib.TalkativeLog('-^-shortcut changed - disabling');
- this._removeKeybindings();
- }
- }
- );
- // start monitoring inputvideo
- this.CtrlWebcam.startMonitor();
- // add indicator
- this.add_child(this.indicatorBox);
- }
- /**
- * @private
- */
- _disable() {
- // remove key binding
- this._removeKeybindings();
- // stop monitoring inputvideo
- this.CtrlWebcam.stopMonitor();
- // unregister mixer control
- this.CtrlAudio.destroy();
- // remove indicator
- this.remove_child(this.indicatorBox);
- }
- /**
- * @private
- */
- _doDelayAction() {
- if (this.isDelayActive) {
- Lib.TalkativeLog(`-*-delay recording called | delay= ${this.TimeSlider.value}`);
- timerD = new Time.TimerDelay(
- Math.floor(this.TimeSlider.value * 100),
- this._doPreCommand,
- this
- );
- timerD.begin();
- } else {
- Lib.TalkativeLog('-*-instant recording called');
- // start recording
- this._doPreCommand();
- }
- }
- /**
- * @private
- */
- _doPreCommand() {
- if (this._settings.getOption('b', Settings.ACTIVE_PRE_CMD_SETTING_KEY)) {
- Lib.TalkativeLog('-*-execute pre command');
- const PreCmd = this._settings.getOption('s', Settings.PRE_CMD_SETTING_KEY);
- this.CtrlExe.Execute(
- PreCmd,
- false,
- res => {
- Lib.TalkativeLog(`-*-pre command final: ${res}`);
- if (res === true) {
- Lib.TalkativeLog('-*-pre command OK');
- this.recorder.start();
- } else {
- Lib.TalkativeLog('-*-pre command ERROR');
- this.CtrlNotify.createNotify(
- _('ERROR PRE COMMAND - See logs for more info'),
- this._icons.off
- );
- }
- },
- line => {
- Lib.TalkativeLog(`-*-pre command output: ${line}`);
- }
- );
- } else {
- this.recorder.start();
- }
- }
- /**
- * @private
- */
- _doRecording() {
- // start/stop record screen
- if (isActive === false) {
- Lib.TalkativeLog('-*-start recording');
- pathFile = '';
- // get selected area
- const optArea = this._settings.getOption('i', Settings.AREA_SCREEN_SETTING_KEY);
- if (optArea > 0) {
- Lib.TalkativeLog(`-*-type of selection of the area to record: ${optArea}`);
- switch (optArea) {
- case 3:
- new Selection.SelectionArea();
- break;
- case 2:
- new Selection.SelectionWindow();
- break;
- case 1:
- new Selection.SelectionDesktop();
- break;
- }
- } else {
- Lib.TalkativeLog('-*-recording full area');
- this._doDelayAction();
- }
- } else {
- Lib.TalkativeLog('-*-stop recording');
- isActive = false;
- this.recorder.stop();
- if (timerC !== null) {
- // stop counting rec
- timerC.halt();
- timerC = null;
- }
- // execute post-command
- this._doPostCommand();
- }
- this.refreshIndicator(false);
- }
- /**
- * @private
- */
- _doPostCommand() {
- if (this._settings.getOption('b', Settings.ACTIVE_POST_CMD_SETTING_KEY)) {
- Lib.TalkativeLog('-*-execute post command');
- // launch cmd after registration
- const tmpCmd = `/usr/bin/sh -c "${this._settings.getOption('s', Settings.POST_CMD_SETTING_KEY)}"`;
- const mapObj = {
- _fpath: pathFile,
- _dirpath: pathFile.substr(0, pathFile.lastIndexOf('/')),
- _fname: pathFile.substr(
- pathFile.lastIndexOf('/') + 1,
- pathFile.length
- ),
- };
- const Cmd = tmpCmd.replace(/_fpath|_dirpath|_fname/gi, match => {
- return mapObj[match];
- });
- Lib.TalkativeLog(`-*-post command:${Cmd}`);
- // execute post command
- this.CtrlExe.Spawn(Cmd);
- }
- }
- /**
- * @param {boolean} result whether the recording was successful
- * @param {string} file file path of the recorded file
- */
- doRecResult(result, file) {
- if (result) {
- isActive = true;
- Lib.TalkativeLog('-*-record OK');
- // update indicator
- const indicators = this._settings.getOption('i', Settings.STATUS_INDICATORS_SETTING_KEY);
- this._replaceStdIndicator(indicators === 1 || indicators === 3);
- if (this.isShowNotify) {
- Lib.TalkativeLog('-*-show notify');
- // create counting notify
- this.notifyCounting = this.CtrlNotify.createNotify(
- _('Start Recording'),
- this._icons.on
- );
- this.notifyCounting.connect('destroy', () => {
- Lib.TalkativeLog('-*-notification destroyed');
- this.notifyCounting = null;
- });
- // start counting rec
- timerC = new Time.TimerCounting((secpassed, alertEnd) => {
- this._refreshNotify(secpassed, alertEnd);
- }, this);
- timerC.begin();
- }
- // update path file video
- pathFile = file;
- Lib.TalkativeLog(`-*-update abs file path -> ${pathFile}`);
- } else {
- Lib.TalkativeLog('-*-record ERROR');
- pathFile = '';
- if (this.isShowNotify) {
- Lib.TalkativeLog('-*-show error notify');
- this.CtrlNotify.createNotify(
- _('ERROR RECORDER - See logs for more info'),
- this._icons.off
- );
- }
- }
- this.refreshIndicator(false);
- }
- /**
- * @param {number} sec the seconds passed
- * @param {boolean} alertEnd whether the timer is ending
- */
- _refreshNotify(sec, alertEnd) {
- if (this.notifyCounting !== null && this.notifyCounting !== undefined && this.isShowNotify) {
- if (alertEnd) {
- this.CtrlNotify.updateNotify(
- this.notifyCounting,
- _(`Finish Recording / Seconds : ${sec}`),
- this._icons.off,
- true
- );
- } else {
- this.CtrlNotify.updateNotify(
- this.notifyCounting,
- _('Recording ... / Seconds passed : ') + sec,
- this._icons.on,
- false
- );
- }
- }
- }
- /**
- * @private
- */
- _openExtensionPreferences() {
- try {
- this._extension.openPreferences();
- } catch (e) {
- Lib.TalkativeLog(`Failed to open preferences: ${e}`);
- }
- }
- /**
- * @private
- */
- _onDelayTimeChanged() {
- const secDelay = Math.floor(this.TimeSlider.value * 100);
- this._settings.setOption(Settings.TIME_DELAY_SETTING_KEY, secDelay);
- if (secDelay > 0)
- this.smDelayRec.label.text = secDelay + _(' sec. delay before recording');
- else
- this.smDelayRec.label.text = _('Start recording immediately');
- }
- /**
- * @param {boolean} focus selects the correct icon depending on the focus state
- */
- refreshIndicator(focus) {
- Lib.TalkativeLog(`-*-refresh indicator -A ${isActive} -F ${focus}`);
- const indicators = this._settings.getOption('i', Settings.STATUS_INDICATORS_SETTING_KEY);
- if (isActive === true) {
- if (indicators === 0 || indicators === 1) {
- if (focus === true)
- this.indicatorIcon.set_gicon(this._icons.onSel);
- else
- this.indicatorIcon.set_gicon(this._icons.on);
- } else if (this._settings.getOption('b', Settings.ACTIVE_SHORTCUT_SETTING_KEY)) {
- this.indicatorIcon.set_gicon(null);
- } else if (focus === true) {
- this.indicatorIcon.set_gicon(this._icons.onSel);
- } else {
- this.indicatorIcon.set_gicon(this._icons.on);
- }
- this.RecordingLabel.set_text(_('Stop recording'));
- } else {
- if (focus === true)
- this.indicatorIcon.set_gicon(this._icons.offSel);
- else
- this.indicatorIcon.set_gicon(this._icons.off);
- this.RecordingLabel.set_text(_('Start recording'));
- }
- }
- /**
- * @param {boolean} OPTtemp whether to replace the standard indicator or use it
- * @private
- */
- _replaceStdIndicator(OPTtemp) {
- if (Main.panel.statusArea === undefined) {
- Lib.TalkativeLog('-*-no Main.panel.statusArea found');
- return;
- }
- var stdMenu = Main.panel.statusArea.quickSettings;
- if (stdMenu === undefined) {
- Lib.TalkativeLog('-*-no quickSettings or aggregateMenu in Main.panel.statusArea');
- return;
- }
- if (stdMenu._remoteAccess === undefined) {
- Lib.TalkativeLog('-*-no _remoteAccess indicator applet found');
- return;
- }
- var indicator = stdMenu._remoteAccess._indicator;
- if (indicator === undefined) {
- Lib.TalkativeLog('-*-no _indicator or _recordingIndicator found');
- return;
- }
- if (OPTtemp) {
- Lib.TalkativeLog('-*-replace STD indicator');
- indicator.visible = false;
- } else {
- Lib.TalkativeLog('-*-use STD indicator');
- indicator.visible = isActive;
- }
- }
- /**
- * @private
- */
- _enableKeybindings() {
- if (this._settings.getOption('b', Settings.ACTIVE_SHORTCUT_SETTING_KEY)) {
- Lib.TalkativeLog('-*-enable keybinding');
- Main.wm.addKeybinding(
- Settings.SHORTCUT_KEY_SETTING_KEY,
- this._settings._settings,
- Meta.KeyBindingFlags.NONE,
- // available modes: https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/src/shell-action-modes.h
- Shell.ActionMode.NORMAL |
- Shell.ActionMode.OVERVIEW |
- Shell.ActionMode.POPUP |
- Shell.ActionMode.SYSTEM_MODAL,
- () => {
- Lib.TalkativeLog('-*-intercept key combination');
- this._doRecording();
- }
- );
- keybindingConfigured = true;
- }
- }
- /**
- * @private
- */
- _removeKeybindings() {
- if (keybindingConfigured) {
- Lib.TalkativeLog('-*-remove keybinding');
- Main.wm.removeKeybinding(Settings.SHORTCUT_KEY_SETTING_KEY);
- keybindingConfigured = false;
- }
- }
- getSelectedRect() {
- var recX = this._settings.getOption('i', Settings.X_POS_SETTING_KEY);
- var recY = this._settings.getOption('i', Settings.Y_POS_SETTING_KEY);
- var recW = this._settings.getOption('i', Settings.WIDTH_SETTING_KEY);
- var recH = this._settings.getOption('i', Settings.HEIGHT_SETTING_KEY);
- return [recX, recY, recW, recH];
- }
- saveSelectedRect(x, y, h, w) {
- this._settings.setOption(Settings.X_POS_SETTING_KEY, x);
- this._settings.setOption(Settings.Y_POS_SETTING_KEY, y);
- this._settings.setOption(Settings.HEIGHT_SETTING_KEY, h);
- this._settings.setOption(Settings.WIDTH_SETTING_KEY, w);
- }
- getSettings() {
- return this._settings;
- }
- getAudioSource() {
- return this.CtrlAudio.getAudioSource();
- }
- /**
- * Destroy indicator
- */
- destroy() {
- Lib.TalkativeLog('-*-destroy indicator called');
- if (isActive)
- isActive = false;
- if (this._settings) {
- this._settings.destroy();
- this._settings = null;
- }
- super.destroy();
- }
- });
- export default class EasyScreenCast extends Extension {
- /**
- *
- */
- enable() {
- Lib.TalkativeLog('-*-enableExtension called');
- Lib.TalkativeLog(`-*-version: ${this.metadata.version}`);
- Lib.TalkativeLog(`-*-install path: ${this.path}`);
- Lib.TalkativeLog(`-*-version (package.json): ${Lib.getFullVersion()}`);
- if (Indicator === null || Indicator === undefined) {
- Lib.TalkativeLog('-*-create indicator');
- Indicator = new EasyScreenCastIndicator(this);
- Main.panel.addToStatusArea('EasyScreenCast-indicator', Indicator);
- }
- Indicator._enable();
- }
- /**
- *
- */
- disable() {
- Lib.TalkativeLog('-*-disableExtension called');
- if (timerD !== null) {
- Lib.TalkativeLog('-*-timerD stopped');
- timerD.stop();
- timerD = null;
- }
- // this might happen, if the extension is disabled during recording
- if (timerC !== null) {
- // stop counting rec
- timerC.halt();
- timerC = null;
- }
- if (Indicator !== null) {
- Lib.TalkativeLog('-*-indicator call destroy');
- Indicator._disable();
- Indicator.destroy();
- Indicator = null;
- }
- }
- }
- export {Indicator};
|