/*
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 GIRepository from 'gi://GIRepository';
GIRepository.Repository.prepend_search_path('/usr/lib64/gnome-shell');
GIRepository.Repository.prepend_library_path('/usr/lib64/gnome-shell');
import Adw from 'gi://Adw';
import GObject from 'gi://GObject';
import Gio from 'gi://Gio';
import Gtk from 'gi://Gtk';
import Gdk from 'gi://Gdk';
import Pango from 'gi://Pango';
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import * as Lib from './convenience.js';
import * as UtilWebcam from './utilwebcam.js';
import * as UtilGSP from './utilgsp.js';
import * as Settings from './settings.js';
import * as UtilExeCmd from './utilexecmd.js';
const EasyScreenCastSettingsWidget = GObject.registerClass({
GTypeName: 'EasyScreenCast_SettingsWidget',
}, class EasyScreenCastSettingsWidget extends Gtk.Box {
/**
* @param {ExtensionPreferences} prefs the prefs instance
*/
constructor(prefs) {
super();
this._prefs = prefs;
this._settings = new Settings.Settings(this._prefs.getSettings());
Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY));
this.CtrlExe = new UtilExeCmd.ExecuteStuff(this);
this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam'));
let cssProvider = new Gtk.CssProvider();
cssProvider.load_from_path(`${prefs.path}/prefs.css`);
Gtk.StyleContext.add_provider_for_display(
Gdk.Display.get_default(),
cssProvider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
// creates the ui builder and add the main resource file
let uiFilePath = `${this._prefs.path}/Options_UI.glade`;
let builder = new Gtk.Builder();
builder.set_translation_domain(this._prefs.metadata['gettext-domain']);
if (builder.add_from_file(uiFilePath) === 0) {
Lib.TalkativeLog(`-^-could not load the ui file: ${uiFilePath}`);
let label = new Gtk.Label({
label: _('Could not load the preferences UI file'),
vexpand: true,
});
this.append(label);
} else {
Lib.TalkativeLog(`-^-UI file receive and load: ${uiFilePath}`);
// gets the interesting builder objects
let refBoxMainContainer = builder.get_object('Main_Container');
this.append(refBoxMainContainer);
// setup tab options
this._initTabOptions(this, builder, this._settings._settings);
// setup tab quality
this._initTabQuality(this, builder, this._settings._settings);
// setup tab webcam
this._initTabWebcam(this, builder, this._settings._settings);
// setup tab file
this._initTabFile(this, builder, this._settings._settings);
// setup tab support
this._initTabSupport(this, builder, this._settings._settings);
// setup tab info
this._initTabInfo(this, builder);
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// update GSP area
this._setStateGSP(
!this._settings.getOption('b', Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY)
);
// update list view
this._updateRowShortcut(
this._settings.getOption('as', Settings.SHORTCUT_KEY_SETTING_KEY)[0]
);
// update webcam widget state
this._updateStateWebcamOptions();
// connect keywebcam signal
this._settings._settings.connect(
`changed::${Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY}`,
() => {
Lib.TalkativeLog('-^-webcam device changed');
this._updateStateWebcamOptions();
}
);
}
}
/**
* @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget
* @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file
* @param {Gio.Settings} tmpS the current settings
* @private
*/
_initTabOptions(ctx, gtkDB, tmpS) {
// implements show timer option
let refSwitchShowNotifyAlert = gtkDB.get_object('swt_ShowNotifyAlert');
tmpS.bind(
Settings.SHOW_NOTIFY_ALERT_SETTING_KEY,
refSwitchShowNotifyAlert,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements show area option
let refSwitchShowAreaRec = gtkDB.get_object('swt_ShowAreaRec');
tmpS.bind(
Settings.SHOW_AREA_REC_SETTING_KEY,
refSwitchShowAreaRec,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements show indicator option
let refComboboxIndicatorsRec = gtkDB.get_object('cbt_StatusIndicatorsRec');
tmpS.bind(
Settings.STATUS_INDICATORS_SETTING_KEY,
refComboboxIndicatorsRec,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements draw cursor option
let refSwitchDrawCursorRec = gtkDB.get_object('swt_DrawCursorRec');
tmpS.bind(
Settings.DRAW_CURSOR_SETTING_KEY,
refSwitchDrawCursorRec,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements enable keybinding option
let refSwitchEnableShortcut = gtkDB.get_object('swt_KeyShortcut');
tmpS.bind(
Settings.ACTIVE_SHORTCUT_SETTING_KEY,
refSwitchEnableShortcut,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements selecting alternative key combo
let refTreeviewShortcut = gtkDB.get_object('treeview_KeyShortcut');
refTreeviewShortcut.set_sensitive(true);
ctx.Ref_liststore_Shortcut = gtkDB.get_object('liststore_KeyShortcut');
ctx.Iter_ShortcutRow = ctx.Ref_liststore_Shortcut.append();
let renderer = new Gtk.CellRendererAccel({
editable: true,
});
renderer.connect(
'accel-edited',
(_0, _1, key, mods, _2) => {
Lib.TalkativeLog(`-^-edited key accel: key=${key} mods=${mods}`);
let accel = Gtk.accelerator_name(key, mods);
ctx._updateRowShortcut(accel);
this._settings.setOption(Settings.SHORTCUT_KEY_SETTING_KEY, [accel]);
}
);
renderer.connect('accel-cleared', () => {
Lib.TalkativeLog('-^-cleared key accel');
ctx._updateRowShortcut(null);
this._settings.setOption(Settings.SHORTCUT_KEY_SETTING_KEY, []);
});
let column = new Gtk.TreeViewColumn();
column.pack_start(renderer, true);
column.add_attribute(
renderer,
'accel-key',
Settings.SHORTCUT_COLUMN_KEY
);
column.add_attribute(
renderer,
'accel-mods',
Settings.SHORTCUT_COLUMN_MODS
);
refTreeviewShortcut.append_column(column);
// implements post execute command
let refSwitchExecutePostCmd = gtkDB.get_object('swt_executepostcmd');
tmpS.bind(
Settings.ACTIVE_POST_CMD_SETTING_KEY,
refSwitchExecutePostCmd,
'active',
Gio.SettingsBindFlags.DEFAULT
);
let refTexteditPostCmd = gtkDB.get_object('txe_postcmd');
tmpS.bind(
Settings.POST_CMD_SETTING_KEY,
refTexteditPostCmd,
'text',
Gio.SettingsBindFlags.DEFAULT
);
// implements pre execute command
let refSwitchExecutePreCmd = gtkDB.get_object('swt_executeprecmd');
tmpS.bind(
Settings.ACTIVE_PRE_CMD_SETTING_KEY,
refSwitchExecutePreCmd,
'active',
Gio.SettingsBindFlags.DEFAULT
);
let refTexteditPreCmd = gtkDB.get_object('txe_precmd');
tmpS.bind(
Settings.PRE_CMD_SETTING_KEY,
refTexteditPreCmd,
'text',
Gio.SettingsBindFlags.DEFAULT
);
}
/**
* @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget
* @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file
* @param {Gio.Settings} tmpS the current settings
* @private
*/
_initTabQuality(ctx, gtkDB, tmpS) {
// implements FPS option
let refSpinnerFrameRateRec = gtkDB.get_object('spb_FrameRateRec');
// Create an adjustment to use for the second spinbutton
let adjustment1 = new Gtk.Adjustment({
value: 30,
lower: 1,
upper: 666,
step_increment: 1,
page_increment: 10,
});
refSpinnerFrameRateRec.configure(adjustment1, 10, 0);
tmpS.bind(
Settings.FPS_SETTING_KEY,
refSpinnerFrameRateRec,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements command string rec option
let refTexteditPipeline = gtkDB.get_object('txe_CommandStringRec');
let refBufferPipeline = refTexteditPipeline.get_buffer();
tmpS.bind(
Settings.PIPELINE_REC_SETTING_KEY,
refBufferPipeline,
'text',
Gio.SettingsBindFlags.DEFAULT
);
// implements label description GSP
let refLabelDescGSP = gtkDB.get_object('lbl_GSP_Description');
refLabelDescGSP.set_text(
UtilGSP.getDescr(
this._settings.getOption('i', Settings.QUALITY_SETTING_KEY),
this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY)
)
);
// update label description when container selection changed
this._settings._settings.connect(`changed::${Settings.FILE_CONTAINER_SETTING_KEY}`, () => {
Lib.TalkativeLog('-^- new setting for file container, update gps description');
refLabelDescGSP.set_text(
UtilGSP.getDescr(
this._settings.getOption('i', Settings.QUALITY_SETTING_KEY),
this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY)
)
);
});
// implements quality scale option
let refScaleQuality = gtkDB.get_object('scl_Quality');
refScaleQuality.set_valign(Gtk.Align.START);
let adjustment2 = new Gtk.Adjustment({
value: 1,
lower: 0,
upper: 3,
step_increment: 1,
page_increment: 1,
});
refScaleQuality.set_adjustment(adjustment2);
refScaleQuality.set_digits(1);
let ind = 0;
for (; ind < 4; ind++)
refScaleQuality.add_mark(ind, Gtk.PositionType.BOTTOM, '');
refScaleQuality.set_value(
this._settings.getOption('i', Settings.QUALITY_SETTING_KEY)
);
let oldQualityValue = refScaleQuality.get_value();
refScaleQuality.connect('value-changed', self => {
// not logging by default - it's too much
// Lib.TalkativeLog(`-^-value quality changed : ${self.get_value()}`);
// round the value
let roundTmp = parseInt(self.get_value().toFixed(0));
// not logging by default - it's too much
// Lib.TalkativeLog(`-^-value quality fixed : ${roundTmp}`);
self.set_value(roundTmp);
// only update labels for real changes
if (oldQualityValue !== roundTmp) {
oldQualityValue = roundTmp;
this._settings.setOption(Settings.QUALITY_SETTING_KEY, roundTmp);
// update label descr GSP
refLabelDescGSP.set_text(
UtilGSP.getDescr(
roundTmp,
this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY)
)
);
// update fps
this._settings.setOption(
Settings.FPS_SETTING_KEY,
UtilGSP.getFps(
roundTmp,
this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY)
)
);
}
});
// implements image for scale widget
let refImagePerformance = gtkDB.get_object('img_Performance');
refImagePerformance.set_from_file(Lib.getImagePath(this._prefs.dir, 'Icon_Performance.svg'));
let refImageQuality = gtkDB.get_object('img_Quality');
refImageQuality.set_from_file(Lib.getImagePath(this._prefs.dir, 'Icon_Quality.svg'));
// implements custom GSPipeline option
let refSwitchCustomGSP = gtkDB.get_object('swt_EnableCustomGSP');
tmpS.bind(
Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY,
refSwitchCustomGSP,
'active',
Gio.SettingsBindFlags.DEFAULT
);
refSwitchCustomGSP.connect('state-set', () => {
// update GSP text area
ctx._setStateGSP(this._settings.getOption('b', Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY));
});
ctx.Ref_stack_Quality = gtkDB.get_object('stk_Quality');
}
/**
* @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget
* @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file
* @param {Gio.Settings} tmpS the current settings
* @private
*/
_initTabWebcam(ctx, gtkDB, tmpS) {
// implements webcam quality option: Type: GtkListStore
ctx.Ref_ListStore_QualityWebCam = gtkDB.get_object(
'liststore_QualityWebCam'
);
let refTreeViewQualityWebCam = gtkDB.get_object(
'treeview_QualityWebam'
);
// create column data
let capsColumn = new Gtk.TreeViewColumn({
title: _('WebCam Caps'),
});
let normalColumn = new Gtk.CellRendererText();
capsColumn.pack_start(normalColumn, true);
capsColumn.add_attribute(normalColumn, 'text', 0);
// insert caps column into treeview
refTreeViewQualityWebCam.insert_column(capsColumn, 0);
// setup selection liststore
let capsSelection = refTreeViewQualityWebCam.get_selection();
// connect selection signal
capsSelection.connect('changed', self => {
let [isSelected,, iter] = self.get_selected();
if (isSelected) {
let Caps = ctx.Ref_ListStore_QualityWebCam.get_value(iter, 0);
Lib.TalkativeLog(`-^-treeview row selected : ${Caps}`);
this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, Caps);
// update label webcam caps
ctx.Ref_Label_WebCamCaps.set_ellipsize(Pango.EllipsizeMode.END);
ctx.Ref_Label_WebCamCaps.set_text(Caps);
}
});
// fill combobox with quality option webcam
ctx._updateWebCamCaps(this._settings.getOption('i', Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY));
// implements webcam corner position option
let refComboboxCornerWebCam = gtkDB.get_object('cbt_WebCamCorner');
tmpS.bind(
Settings.CORNER_POSITION_WEBCAM_SETTING_KEY,
refComboboxCornerWebCam,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam margin x position option
let refSpinnerMarginXWebCam = gtkDB.get_object('spb_WebCamMarginX');
let adjustmentMarginX = new Gtk.Adjustment({
value: 0,
lower: 0,
upper: 10000,
step_increment: 1,
page_increment: 10,
});
refSpinnerMarginXWebCam.configure(adjustmentMarginX, 10, 0);
tmpS.bind(
Settings.MARGIN_X_WEBCAM_SETTING_KEY,
refSpinnerMarginXWebCam,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam margin y position option
let refSpinnerMarginYWebCam = gtkDB.get_object('spb_WebCamMarginY');
let adjustmentMarginY = new Gtk.Adjustment({
value: 0,
lower: 0,
upper: 10000,
step_increment: 1,
page_increment: 10,
});
refSpinnerMarginYWebCam.configure(adjustmentMarginY, 10, 0);
tmpS.bind(
Settings.MARGIN_Y_WEBCAM_SETTING_KEY,
refSpinnerMarginYWebCam,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam aplha channel option
let refSpinnerAlphaWebCam = gtkDB.get_object('spb_WebCamAlpha');
let adjustmentAlpha = new Gtk.Adjustment({
value: 0.01,
lower: 0.0,
upper: 1.0,
step_increment: 0.05,
page_increment: 0.25,
});
refSpinnerAlphaWebCam.configure(adjustmentAlpha, 0.25, 2);
tmpS.bind(
Settings.ALPHA_CHANNEL_WEBCAM_SETTING_KEY,
refSpinnerAlphaWebCam,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam type unit dimension option
let refComboboxTypeUnitWebCam = gtkDB.get_object('cbt_WebCamUnitMeasure');
tmpS.bind(
Settings.TYPE_UNIT_WEBCAM_SETTING_KEY,
refComboboxTypeUnitWebCam,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam width option
let refSpinnerWidthWebCam = gtkDB.get_object('spb_WebCamWidth');
let adjustmentWidth = new Gtk.Adjustment({
value: 20,
lower: 0,
upper: 10000,
step_increment: 1,
page_increment: 10,
});
refSpinnerWidthWebCam.configure(adjustmentWidth, 10, 0);
tmpS.bind(
Settings.WIDTH_WEBCAM_SETTING_KEY,
refSpinnerWidthWebCam,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam heigth option
let refSpinnerHeightWebCam = gtkDB.get_object('spb_WebCamHeight');
let adjustmentHeight = new Gtk.Adjustment({
value: 10,
lower: 0,
upper: 10000,
step_increment: 1,
page_increment: 10,
});
refSpinnerHeightWebCam.configure(adjustmentHeight, 10, 0);
tmpS.bind(
Settings.HEIGHT_WEBCAM_SETTING_KEY,
refSpinnerHeightWebCam,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements webcam stack menu chooser
ctx.Ref_StackSwitcher_WebCam = gtkDB.get_object('sts_Webcam');
// implements webcam stack obj
ctx.Ref_StackObj_WebCam = gtkDB.get_object('stk_Webcam');
// implements webcam stack menu chooser
ctx.Ref_Label_WebCam = gtkDB.get_object('lbl_Webcam');
// implements webcam caps stack menu chooser
ctx.Ref_Label_WebCamCaps = gtkDB.get_object('lbl_WebcamCaps');
}
/**
* @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget
* @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file
* @param {Gio.Settings} tmpS the current settings
* @private
*/
_initTabFile(ctx, gtkDB, tmpS) {
// implements file name string rec option
let refTexteditFileName = gtkDB.get_object('txe_FileNameRec');
tmpS.bind(
Settings.FILE_NAME_SETTING_KEY,
refTexteditFileName,
'text',
Gio.SettingsBindFlags.DEFAULT
);
// implements file container option
let refComboboxContainer = gtkDB.get_object('cbt_FileContainer');
tmpS.bind(
Settings.FILE_CONTAINER_SETTING_KEY,
refComboboxContainer,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements file container resolution
let refStackFileResolution = gtkDB.get_object('stk_FileResolution');
// implements file resolution preset spinner
let refComboboxResolution = gtkDB.get_object('cbt_FileResolution');
tmpS.bind(
Settings.FILE_RESOLUTION_TYPE_SETTING_KEY,
refComboboxResolution,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// intercept combobox res changed and update width/height value
refComboboxResolution.connect('changed', self => {
var activeRes = self.active;
Lib.TalkativeLog(`-^-preset combobox changed: ${activeRes}`);
if (activeRes >= 0 && activeRes < 15) {
var [h, w] = ctx._getResolutionPreset(activeRes);
// update width/height
this._settings.setOption(Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY, h);
this._settings.setOption(Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY, w);
Lib.TalkativeLog(`-^-Res changed h: ${h} w: ${w}`);
}
});
// load file resolution pref and upadte UI
var tmpRes = this._settings.getOption('i', Settings.FILE_RESOLUTION_TYPE_SETTING_KEY);
if (tmpRes < 0)
refStackFileResolution.set_visible_child_name('native');
else if (tmpRes === 999)
refStackFileResolution.set_visible_child_name('custom');
else
refStackFileResolution.set_visible_child_name('preset');
// setup event on stack switcher
refStackFileResolution.connect('notify::visible-child-name', () => {
Lib.TalkativeLog('-^-stack_FR event grab');
var page = refStackFileResolution.get_visible_child_name();
Lib.TalkativeLog(`-^-active page -> ${page}`);
if (page === 'native') {
// set option to -1
this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, -1);
} else if (page === 'preset') {
// set option to fullHD 16:9
this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, 8);
} else if (page === 'custom') {
// set option to 99
this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, 999);
} else {
Lib.TalkativeLog('-^-page error');
}
});
// implements file width option
let refSpinnerWidthRes = gtkDB.get_object('spb_ResWidth');
let adjustmentResWidth = new Gtk.Adjustment({
value: 640,
lower: 640,
upper: 3840,
step_increment: 1,
page_increment: 100,
});
refSpinnerWidthRes.configure(adjustmentResWidth, 10, 0);
tmpS.bind(
Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY,
refSpinnerWidthRes,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements file heigth option
let refSpinnerHeightRes = gtkDB.get_object('spb_ResHeight');
let adjustmentResHeight = new Gtk.Adjustment({
value: 480,
lower: 480,
upper: 2160,
step_increment: 1,
page_increment: 100,
});
refSpinnerHeightRes.configure(adjustmentResHeight, 10, 0);
tmpS.bind(
Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY,
refSpinnerHeightRes,
'value',
Gio.SettingsBindFlags.DEFAULT
);
// implements keep aspect ratio check box
let refCheckboxKeepAspectRatio = gtkDB.get_object('chb_FileResolution_kar');
tmpS.bind(
Settings.FILE_RESOLUTION_KAR_SETTING_KEY,
refCheckboxKeepAspectRatio,
'active',
Gio.SettingsBindFlags.DEFAULT
);
// implements resolution width scale option
let refScaleWidthRes = gtkDB.get_object('scl_ResWidth');
refScaleWidthRes.set_valign(Gtk.Align.START);
refScaleWidthRes.set_adjustment(adjustmentResWidth);
refScaleWidthRes.set_digits(0);
refScaleWidthRes.set_value(this._settings.getOption('i', Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY));
// implements resolution height scale option
let refScaleHeightRes = gtkDB.get_object('scl_ResHeight');
refScaleHeightRes.set_valign(Gtk.Align.START);
refScaleHeightRes.set_adjustment(adjustmentResHeight);
refScaleHeightRes.set_digits(0);
refScaleHeightRes.set_value(this._settings.getOption('i', Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY));
// add marks on width/height file resolution
let ind = 0;
for (; ind < 13; ind++) {
var [h, w] = ctx._getResolutionPreset(ind);
refScaleWidthRes.add_mark(w, Gtk.PositionType.BOTTOM, '');
refScaleHeightRes.add_mark(h, Gtk.PositionType.BOTTOM, '');
}
// implements file folder string rec option
let refFilechooserFileFolder = gtkDB.get_object('fcb_FilePathRec');
// check state initial value
var tmpFolder = this._settings.getOption('s', Settings.FILE_FOLDER_SETTING_KEY);
Lib.TalkativeLog(`-^-folder for screencast: ${tmpFolder}`);
if (tmpFolder === '' || tmpFolder === null || tmpFolder === undefined) {
let result = null;
ctx.CtrlExe.Execute(
'xdg-user-dir VIDEOS',
true,
(success, out) => {
Lib.TalkativeLog(`-^-CALLBACK sync S: ${success} out: ${out}`);
if (success && out !== '' && out !== undefined)
result = out.replace(/(\n)/g, '');
},
null
);
if (result !== null) {
Lib.TalkativeLog(`-^-xdg-user video: ${result}`);
tmpFolder = result;
} else {
Lib.TalkativeLog('-^-NOT SET xdg-user video');
ctx.CtrlExe.Execute(
'/usr/bin/sh -c "echo $HOME"',
true,
(success, out) => {
Lib.TalkativeLog(`-^-CALLBACK sync S: ${success} out: ${out}`);
if (success && out !== '' && out !== undefined)
tmpFolder = out.replace(/(\n)/g, '');
},
null
);
}
// connect keywebcam signal
this._settings._settings.connect(
`changed::${Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY}`,
() => {
Lib.TalkativeLog('-^-webcam device changed');
this._refreshWebcamOptions();
}
);
}
refFilechooserFileFolder.set_label(`Selected: ${tmpFolder}`);
refFilechooserFileFolder.connect('clicked', () => {
Lib.TalkativeLog('-^- file chooser button clicked...');
let dialog = new Gtk.FileChooserNative({
'title': 'Select folder',
'transient-for': refFilechooserFileFolder.get_root(),
'action': Gtk.FileChooserAction.SELECT_FOLDER,
'accept-label': 'Ok',
'cancel-label': 'Cancel',
});
dialog.connect('response', (self, response) => {
if (response === Gtk.ResponseType.ACCEPT) {
var tmpPathFolder = self.get_file().get_path();
Lib.TalkativeLog(`-^-file path get from widget : ${tmpPathFolder}`);
this._settings.setOption(
Settings.FILE_FOLDER_SETTING_KEY,
tmpPathFolder
);
refFilechooserFileFolder.set_label(`Selected: ${tmpPathFolder}`);
}
ctx.fileChooserDialog = null;
});
dialog.show();
ctx.fileChooserDialog = dialog; // keep a reference to the dialog alive
});
}
/**
* @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget
* @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file
* @param {Gio.Settings} tmpS the current settings
* @private
*/
_initTabSupport(ctx, gtkDB, tmpS) {
// implements textentry log
let refTextViewEscLog = gtkDB.get_object('txe_ContainerLog');
let refBufferLog = refTextViewEscLog.get_buffer();
// implements verbose debug option
let refSwitchVerboseDebug = gtkDB.get_object('swt_VerboseDebug');
tmpS.bind(
Settings.VERBOSE_DEBUG_SETTING_KEY,
refSwitchVerboseDebug,
'active',
Gio.SettingsBindFlags.DEFAULT
);
this._settings._settings.connect(
`changed::${Settings.VERBOSE_DEBUG_SETTING_KEY}`,
() => {
Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY));
}
);
refSwitchVerboseDebug.connect('state-set', self => {
// update log display widgets
refTextViewEscLog.sensistive = self.active;
refComboboxLogChooser.sensitive = self.active;
});
// implements file resolution preset spinner
let refComboboxLogChooser = gtkDB.get_object('cbt_LogChooser');
// intercept combobox res changed and update width/height value
refComboboxLogChooser.connect('changed', self => {
const activeLog = self.active;
Lib.TalkativeLog(`-^-log combobox changed: ${activeLog}`);
switch (activeLog) {
case 0:
// clear buffer
refBufferLog.delete(
refBufferLog.get_start_iter(),
refBufferLog.get_end_iter()
);
ctx.CtrlExe.Execute(
'journalctl --since "15 min ago" --output=cat --no-pager',
false,
success => {
Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`);
},
line => {
let esc = line.indexOf('[ESC]');
if (
line !== '' &&
line !== undefined &&
esc !== -1
) {
line += '\n';
refBufferLog.insert(
refBufferLog.get_end_iter(),
line,
line.length
);
}
}
);
break;
case 1:
// clear buffer
refBufferLog.delete(
refBufferLog.get_start_iter(),
refBufferLog.get_end_iter()
);
ctx.CtrlExe.Execute(
'journalctl --since "15 min ago" --output=cat --no-pager',
false,
success => {
Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`);
if (success) {
if (refBufferLog.get_line_count() > 0) {
let strNOgsp = _(
'No Gstreamer pipeline found'
);
refBufferLog.insert(
refBufferLog.get_end_iter(),
strNOgsp,
strNOgsp.length
);
}
}
},
line => {
let esc = line.indexOf('-ยง-final GSP :');
if (
line !== '' &&
line !== undefined &&
esc !== -1
) {
line += '\n';
refBufferLog.insert(
refBufferLog.get_end_iter(),
line,
line.length
);
}
}
);
break;
case 2:
// clear buffer
refBufferLog.delete(
refBufferLog.get_start_iter(),
refBufferLog.get_end_iter()
);
ctx.CtrlExe.Execute(
'journalctl /usr/bin/gnome-shell --since "15 min ago" --output=cat --no-pager',
false,
success => {
Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`);
},
line => {
if (line !== '' && line !== undefined) {
line += '\n';
refBufferLog.insert(
refBufferLog.get_end_iter(),
line,
line.length
);
}
}
);
break;
default:
break;
}
});
// update state of get log
refComboboxLogChooser.sensistive = this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY);
// implements default button action
let refButtonSetDefaultSettings = gtkDB.get_object('btn_DefaultOption');
refButtonSetDefaultSettings.connect('clicked', () =>
ctx._setDefaultsettings()
);
}
/**
* @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget
* @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file
* @private
*/
_initTabInfo(ctx, gtkDB) {
// implements info img extension
let refImageEsc = gtkDB.get_object('img_ESC');
refImageEsc.set_from_file(Lib.getImagePath(this._prefs.dir, 'Icon_Info.png'));
// implements info version label
let refLabelVersion = gtkDB.get_object('lbl_Version');
refLabelVersion.set_markup(`${_('Version: ')}${this._prefs.metadata.version} (${Lib.getFullVersion()})`);
}
/**
* @param {number} device device index
* @private
*/
_updateWebCamCaps(device) {
Lib.TalkativeLog(`-^-webcam device index: ${device}`);
if (device > 0) {
this._initializeWebcamHelper();
var listCaps = this.CtrlWebcam.getListCapsDevice(device - 1);
Lib.TalkativeLog(`-^-webcam caps: ${listCaps.length}`);
if (listCaps !== null && listCaps !== undefined) {
this.Ref_ListStore_QualityWebCam.clear();
for (var index in listCaps) {
this.Ref_ListStore_QualityWebCam.set(
this.Ref_ListStore_QualityWebCam.append(),
[0],
[listCaps[index]]
);
}
} else {
Lib.TalkativeLog('-^-NO List Caps Webcam');
this.Ref_ListStore_QualityWebCam.clear();
this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, '');
}
} else {
Lib.TalkativeLog('-^-NO Webcam recording');
this.Ref_ListStore_QualityWebCam.clear();
this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, '');
}
}
/**
* Refreshes the webcam settings.
*
* @private
*/
_refreshWebcamOptions() {
Lib.TalkativeLog('-^-refresh webcam options');
this._initializeWebcamHelper();
// fill combobox with quality option webcam
this._updateWebCamCaps(this._settings.getOption('i', Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY));
// update webcam widget state
this._updateStateWebcamOptions();
}
/**
* Initializes this.CtrlWebcam if it is null.
*
* @private
*/
_initializeWebcamHelper() {
if (this.CtrlWebcam === null)
this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam'));
}
/**
* @param {string} accel accelerator string parsable by Gtk.accelerator_parse, e.g. "<Super>E"
* @private
*/
_updateRowShortcut(accel) {
Lib.TalkativeLog(`-^-update row combo key accel: ${accel}`);
let [key, mods] = [0, 0];
if (accel !== null && accel !== undefined) {
let ok;
[ok, key, mods] = Gtk.accelerator_parse(accel);
if (ok !== true) {
Lib.TalkativeLog('-^-couldn\'t parse accel');
key = 0;
mods = 0;
}
}
Lib.TalkativeLog(`-^-key: ${key} mods: ${mods}`);
this.Ref_liststore_Shortcut.set(
this.Iter_ShortcutRow,
[Settings.SHORTCUT_COLUMN_KEY, Settings.SHORTCUT_COLUMN_MODS],
[key, mods]
);
}
/**
* @param {boolean} active custom or not custom GStream pipeline
* @private
*/
_setStateGSP(active) {
// update GSP text area
if (!active) {
Lib.TalkativeLog('-^-custom GSP');
this.Ref_stack_Quality.set_visible_child_name('pg_Custom');
} else {
Lib.TalkativeLog('-^-NOT custom GSP');
this.Ref_stack_Quality.set_visible_child_name('pg_Preset');
var audio = false;
if (this._settings.getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY) > 0)
audio = true;
this._settings.setOption(
Settings.PIPELINE_REC_SETTING_KEY,
Settings.getGSPstd(audio)
);
}
}
/**
* @private
*/
_updateStateWebcamOptions() {
Lib.TalkativeLog('-^-update webcam option widgets');
var tmpDev = this._settings.getOption(
'i',
Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY
);
this._updateWebCamCaps(tmpDev);
if (tmpDev > 0) {
var arrDev = this.CtrlWebcam.getNameDevices();
this.Ref_Label_WebCam.set_text(arrDev[tmpDev - 1]);
// setup label webcam caps
var tmpCaps = this._settings.getOption(
's',
Settings.QUALITY_WEBCAM_SETTING_KEY
);
if (tmpCaps === '') {
this.Ref_Label_WebCamCaps.use_markup = true;
this.Ref_Label_WebCamCaps.set_markup(
_(
'No Caps selected, please select one from the caps list'
)
);
} else {
this.Ref_Label_WebCamCaps.set_text(tmpCaps);
}
// webcam recording show widget
this.Ref_StackSwitcher_WebCam.set_sensitive(true);
this.Ref_StackObj_WebCam.set_sensitive(true);
} else {
this.Ref_Label_WebCam.set_text(_('No webcam device selected'));
// setup label webcam caps
this.Ref_Label_WebCamCaps.set_text(_('-'));
// webcam NOT recording hide widget
this.Ref_StackSwitcher_WebCam.set_sensitive(false);
this.Ref_StackObj_WebCam.set_sensitive(false);
}
}
/**
* @param {number} index index of the predefined resolutions
* @returns {Array}
* @private
*/
_getResolutionPreset(index) {
var arrRes = [
[480, 640],
[480, 854],
[600, 800],
[720, 960],
[720, 1280],
[768, 1024],
[768, 1366],
[1024, 1280],
[1080, 1920],
[1200, 1600],
[1440, 2560],
[2048, 2560],
[2160, 3840],
];
if (index >= 0 && index < arrRes.length)
return arrRes[index];
else
return null;
}
/**
* function to restore default value of the settings
*
* @private
*/
_setDefaultsettings() {
Lib.TalkativeLog('-^-restore default option');
this._settings.setOption(Settings.SHOW_NOTIFY_ALERT_SETTING_KEY, true);
this._settings.setOption(Settings.SHOW_AREA_REC_SETTING_KEY, false);
this._settings.setOption(Settings.STATUS_INDICATORS_SETTING_KEY, 1);
this._settings.setOption(Settings.DRAW_CURSOR_SETTING_KEY, true);
this._settings.setOption(Settings.VERBOSE_DEBUG_SETTING_KEY, false);
this._settings.setOption(Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY, false);
this._settings.setOption(Settings.FPS_SETTING_KEY, 30);
this._settings.setOption(Settings.X_POS_SETTING_KEY, 0);
this._settings.setOption(Settings.Y_POS_SETTING_KEY, 0);
this._settings.setOption(Settings.WIDTH_SETTING_KEY, 600);
this._settings.setOption(Settings.HEIGHT_SETTING_KEY, 400);
this._settings.setOption(Settings.FILE_NAME_SETTING_KEY, 'Screencast_%d_%t');
this._settings.setOption(Settings.FILE_FOLDER_SETTING_KEY, '');
this._settings.setOption(Settings.ACTIVE_POST_CMD_SETTING_KEY, false);
this._settings.setOption(Settings.ACTIVE_PRE_CMD_SETTING_KEY, false);
this._settings.setOption(Settings.POST_CMD_SETTING_KEY, 'xdg-open _fpath &');
this._settings.setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, 0);
this._settings.setOption(Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY, 0);
this._settings.setOption(Settings.DEVICE_WEBCAM_SETTING_KEY, '');
this._settings.setOption(Settings.TIME_DELAY_SETTING_KEY, 0);
this._settings.setOption(Settings.FILE_CONTAINER_SETTING_KEY, 0);
this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, -1);
this._settings.setOption(Settings.QUALITY_SETTING_KEY, 1);
this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, '');
this._settings.setOption(Settings.WIDTH_WEBCAM_SETTING_KEY, 20);
this._settings.setOption(Settings.HEIGHT_WEBCAM_SETTING_KEY, 10);
this._settings.setOption(Settings.TYPE_UNIT_WEBCAM_SETTING_KEY, 0);
this._settings.setOption(Settings.MARGIN_X_WEBCAM_SETTING_KEY, 0);
this._settings.setOption(Settings.MARGIN_Y_WEBCAM_SETTING_KEY, 0);
this._settings.setOption(Settings.ALPHA_CHANNEL_WEBCAM_SETTING_KEY, 0.75);
this._settings.setOption(Settings.CORNER_POSITION_WEBCAM_SETTING_KEY, 0);
}
});
export default class EasyScreenCastPreferences extends ExtensionPreferences {
/**
* @param {Adw.PreferencesWindow} window preferences window?
* @returns {EasyScreenCastSettingsWidget}
*/
fillPreferencesWindow(window) {
window._settings = this.getSettings();
Lib.TalkativeLog('-^-Init pref widget');
const page = new Adw.PreferencesPage();
const group = new Adw.PreferencesGroup({
title: _('EasyScreenCast'),
});
page.add(group);
const widget = new EasyScreenCastSettingsWidget(this);
group.add(widget);
window.add(page);
}
}