mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 15:52:10 +02:00
Port preferences window to libadwaita
This commit is contained in:
@@ -6,35 +6,31 @@
|
|||||||
<default>false</default>
|
<default>false</default>
|
||||||
<summary>Automatically enter fullscreen when first file is loaded</summary>
|
<summary>Automatically enter fullscreen when first file is loaded</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="volume-initial" type="s">
|
<key name="volume-custom" type="b">
|
||||||
<default>"restore"</default>
|
<default>false</default>
|
||||||
<summary>Mode used for startup volume value</summary>
|
<summary>Set custom volume value at startup</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="volume-value" type="i">
|
<key name="volume-value" type="i">
|
||||||
<default>100</default>
|
<default>100</default>
|
||||||
<summary>Custom initial volume value in percentage after startup</summary>
|
<summary>Custom initial volume value in percentage after startup</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="keep-last-frame" type="b">
|
<key name="after-playback" type="i">
|
||||||
<default>false</default>
|
<default>0</default>
|
||||||
<summary>Keep showing last video frame after playback finishes</summary>
|
<summary>What to do after playback finishes</summary>
|
||||||
</key>
|
|
||||||
<key name="close-auto" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<summary>Automatically close the app after playback finishes</summary>
|
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
<!-- Behaviour -->
|
<!-- Behavior -->
|
||||||
<key name="seeking-mode" type="s">
|
<key name="seeking-mode" type="i">
|
||||||
<default>"normal"</default>
|
<default>0</default>
|
||||||
<summary>Mode used for seeking</summary>
|
<summary>Mode used for seeking</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="seeking-value" type="i">
|
<key name="seeking-value" type="i">
|
||||||
<default>10</default>
|
<default>10</default>
|
||||||
<summary>Time amount to seek with single press of arrow keys</summary>
|
<summary>Time amount to seek with single press of arrow keys</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="seeking-unit" type="s">
|
<key name="seeking-unit" type="i">
|
||||||
<default>"second"</default>
|
<default>0</default>
|
||||||
<summary>Unit to use with seeking value</summary>
|
<summary>Unit ID to use with seeking value</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="resume-enabled" type="b">
|
<key name="resume-enabled" type="b">
|
||||||
<default>true</default>
|
<default>true</default>
|
||||||
@@ -50,13 +46,13 @@
|
|||||||
</key>
|
</key>
|
||||||
|
|
||||||
<!-- Audio -->
|
<!-- Audio -->
|
||||||
<key name="audio-offset" type="d">
|
<key name="audio-offset" type="i">
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
<summary>Offset time for audio tracks relative to video (milliseconds)</summary>
|
<summary>Offset time for audio tracks relative to video (milliseconds)</summary>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
<!-- Subtitles -->
|
<!-- Subtitles -->
|
||||||
<key name="subtitle-offset" type="d">
|
<key name="subtitle-offset" type="i">
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
<summary>Offset time for subtitle tracks relative to video (milliseconds)</summary>
|
<summary>Offset time for subtitle tracks relative to video (milliseconds)</summary>
|
||||||
</key>
|
</key>
|
||||||
@@ -95,7 +91,7 @@
|
|||||||
|
|
||||||
<!-- GStreamer -->
|
<!-- GStreamer -->
|
||||||
<key name="plugin-ranking" type="s">
|
<key name="plugin-ranking" type="s">
|
||||||
<default>'[{"apply":false,"name":"vah264dec","rank":300}]'</default>
|
<default>'{}'</default>
|
||||||
<summary>Custom values for GStreamer plugin ranking</summary>
|
<summary>Custom values for GStreamer plugin ranking</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="play-flags" type="i">
|
<key name="play-flags" type="i">
|
||||||
@@ -108,8 +104,8 @@
|
|||||||
<default>false</default>
|
<default>false</default>
|
||||||
<summary>Enable to use adaptive streaming for YouTube</summary>
|
<summary>Enable to use adaptive streaming for YouTube</summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="yt-quality-type" type="s">
|
<key name="yt-quality-type" type="i">
|
||||||
<default>"hfr"</default>
|
<default>1</default>
|
||||||
<summary>Max YouTube video quality type</summary>
|
<summary>Max YouTube video quality type</summary>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
const { Gtk } = imports.gi;
|
const { Gtk } = imports.gi;
|
||||||
const Dialogs = imports.src.dialogs;
|
const Dialogs = imports.src.dialogs;
|
||||||
|
const Prefs = imports.src.prefs;
|
||||||
const Misc = imports.src.misc;
|
const Misc = imports.src.misc;
|
||||||
|
|
||||||
var actions = {
|
var actions = {
|
||||||
@@ -42,7 +43,7 @@ function handleAction(action, window)
|
|||||||
new Dialogs.UriDialog(window);
|
new Dialogs.UriDialog(window);
|
||||||
break;
|
break;
|
||||||
case 'prefs':
|
case 'prefs':
|
||||||
new Dialogs.PrefsDialog(window);
|
new Prefs.PrefsWindow(window);
|
||||||
break;
|
break;
|
||||||
case 'shortcuts':
|
case 'shortcuts':
|
||||||
if(!window.get_help_overlay()) {
|
if(!window.get_help_overlay()) {
|
||||||
|
2
src/controls.js
vendored
2
src/controls.js
vendored
@@ -469,7 +469,7 @@ class ClapperControls extends Gtk.Box
|
|||||||
scrollController.connect('scroll', clapperWidget._onScroll.bind(clapperWidget));
|
scrollController.connect('scroll', clapperWidget._onScroll.bind(clapperWidget));
|
||||||
this.volumeButton.add_controller(scrollController);
|
this.volumeButton.add_controller(scrollController);
|
||||||
|
|
||||||
const initialVolume = (settings.get_string('volume-initial') === 'custom')
|
const initialVolume = (settings.get_boolean('volume-custom'))
|
||||||
? settings.get_int('volume-value') / 100
|
? settings.get_int('volume-value') / 100
|
||||||
: settings.get_double('volume-last');
|
: settings.get_double('volume-last');
|
||||||
|
|
||||||
|
@@ -3,8 +3,6 @@ const System = imports.system;
|
|||||||
const Debug = imports.src.debug;
|
const Debug = imports.src.debug;
|
||||||
const FileOps = imports.src.fileOps;
|
const FileOps = imports.src.fileOps;
|
||||||
const Misc = imports.src.misc;
|
const Misc = imports.src.misc;
|
||||||
const Prefs = imports.src.prefs;
|
|
||||||
const PrefsBase = imports.src.prefsBase;
|
|
||||||
|
|
||||||
const { debug } = Debug;
|
const { debug } = Debug;
|
||||||
|
|
||||||
@@ -247,88 +245,6 @@ class ClapperResumeDialog extends Gtk.MessageDialog
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var PrefsDialog = GObject.registerClass(
|
|
||||||
class ClapperPrefsDialog extends Gtk.Dialog
|
|
||||||
{
|
|
||||||
_init(window)
|
|
||||||
{
|
|
||||||
super._init({
|
|
||||||
transient_for: window,
|
|
||||||
destroy_with_parent: true,
|
|
||||||
modal: true,
|
|
||||||
title: 'Preferences',
|
|
||||||
default_width: 460,
|
|
||||||
default_height: 400,
|
|
||||||
});
|
|
||||||
|
|
||||||
const pages = [
|
|
||||||
{
|
|
||||||
title: 'Player',
|
|
||||||
pages: [
|
|
||||||
{
|
|
||||||
title: 'General',
|
|
||||||
widget: Prefs.GeneralPage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Behaviour',
|
|
||||||
widget: Prefs.BehaviourPage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Audio',
|
|
||||||
widget: Prefs.AudioPage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Subtitles',
|
|
||||||
widget: Prefs.SubtitlesPage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Network',
|
|
||||||
widget: Prefs.NetworkPage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'YouTube',
|
|
||||||
widget: Prefs.YouTubePage,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Advanced',
|
|
||||||
pages: [
|
|
||||||
{
|
|
||||||
title: 'GStreamer',
|
|
||||||
widget: Prefs.GStreamerPage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Tweaks',
|
|
||||||
widget: Prefs.TweaksPage,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const prefsNotebook = new PrefsBase.Notebook(pages);
|
|
||||||
prefsNotebook.add_css_class('prefsnotebook');
|
|
||||||
|
|
||||||
const area = this.get_content_area();
|
|
||||||
area.append(prefsNotebook);
|
|
||||||
|
|
||||||
this.closeSignal = this.connect('close-request', this._onCloseRequest.bind(this));
|
|
||||||
this.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onCloseRequest(dialog)
|
|
||||||
{
|
|
||||||
debug('closing prefs dialog');
|
|
||||||
|
|
||||||
dialog.disconnect(this.closeSignal);
|
|
||||||
this.closeSignal = null;
|
|
||||||
|
|
||||||
const area = dialog.get_content_area();
|
|
||||||
const notebook = area.get_first_child();
|
|
||||||
notebook._onClose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var AboutDialog = GObject.registerClass(
|
var AboutDialog = GObject.registerClass(
|
||||||
class ClapperAboutDialog extends Gtk.AboutDialog
|
class ClapperAboutDialog extends Gtk.AboutDialog
|
||||||
{
|
{
|
||||||
|
@@ -44,7 +44,7 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
this.ytClient = null;
|
this.ytClient = null;
|
||||||
this.playlistWidget = new PlaylistWidget();
|
this.playlistWidget = new PlaylistWidget();
|
||||||
|
|
||||||
this.seek_done = true;
|
this.seekDone = true;
|
||||||
this.needsFastSeekRestore = false;
|
this.needsFastSeekRestore = false;
|
||||||
this.customVideoTitle = null;
|
this.customVideoTitle = null;
|
||||||
|
|
||||||
@@ -70,6 +70,7 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
set_and_bind_settings()
|
set_and_bind_settings()
|
||||||
{
|
{
|
||||||
const settingsToSet = [
|
const settingsToSet = [
|
||||||
|
'after-playback',
|
||||||
'seeking-mode',
|
'seeking-mode',
|
||||||
'audio-offset',
|
'audio-offset',
|
||||||
'subtitle-offset',
|
'subtitle-offset',
|
||||||
@@ -81,7 +82,6 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
this._onSettingsKeyChanged(settings, key);
|
this._onSettingsKeyChanged(settings, key);
|
||||||
|
|
||||||
const flag = Gio.SettingsBindFlags.GET;
|
const flag = Gio.SettingsBindFlags.GET;
|
||||||
settings.bind('keep-last-frame', this.widget, 'keep-last-frame', flag);
|
|
||||||
settings.bind('subtitle-font', this.pipeline, 'subtitle-font-desc', flag);
|
settings.bind('subtitle-font', this.pipeline, 'subtitle-font-desc', flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,25 +96,23 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
|
|
||||||
set_all_plugins_ranks()
|
set_all_plugins_ranks()
|
||||||
{
|
{
|
||||||
let data = [];
|
let data = {};
|
||||||
|
|
||||||
/* Set empty plugin list if someone messed it externally */
|
/* Set empty plugin list if someone messed it externally */
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(settings.get_string('plugin-ranking'));
|
data = JSON.parse(settings.get_string('plugin-ranking'));
|
||||||
if(!Array.isArray(data))
|
if(Array.isArray(data)) {
|
||||||
throw new Error('plugin ranking data is not an array!');
|
data = {};
|
||||||
|
throw new Error('plugin ranking data is not an object');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
debug(err);
|
debug(err);
|
||||||
settings.set_string('plugin-ranking', "[]");
|
settings.set_string('plugin-ranking', "{}");
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let plugin of data) {
|
for(let plugin of Object.keys(data))
|
||||||
if(!plugin.apply || !plugin.name)
|
this.set_plugin_rank(plugin, data[plugin]);
|
||||||
continue;
|
|
||||||
|
|
||||||
this.set_plugin_rank(plugin.name, plugin.rank);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_plugin_rank(name, rank)
|
set_plugin_rank(name, rank)
|
||||||
@@ -284,7 +282,7 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
if(this.needsTocUpdate)
|
if(this.needsTocUpdate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.seek_done = false;
|
this.seekDone = false;
|
||||||
|
|
||||||
if(this.state === GstClapper.ClapperState.STOPPED)
|
if(this.state === GstClapper.ClapperState.STOPPED)
|
||||||
this.pause();
|
this.pause();
|
||||||
@@ -292,8 +290,6 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
if(position < 0)
|
if(position < 0)
|
||||||
position = 0;
|
position = 0;
|
||||||
|
|
||||||
debug(`${this.seekingMode} seeking to position: ${position}`);
|
|
||||||
|
|
||||||
super.seek(position);
|
super.seek(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,13 +300,12 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
|
|
||||||
seek_chapter(seconds)
|
seek_chapter(seconds)
|
||||||
{
|
{
|
||||||
if(this.seekingMode !== 'fast') {
|
if(this.seek_mode !== GstClapper.ClapperSeekMode.FAST) {
|
||||||
this.seek_seconds(seconds);
|
this.seek_seconds(seconds);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set_seek_mode(GstClapper.ClapperSeekMode.DEFAULT);
|
this.set_seek_mode(GstClapper.ClapperSeekMode.DEFAULT);
|
||||||
this.seekingMode = 'normal';
|
|
||||||
this.needsFastSeekRestore = true;
|
this.needsFastSeekRestore = true;
|
||||||
|
|
||||||
this.seek_seconds(seconds);
|
this.seek_seconds(seconds);
|
||||||
@@ -318,20 +313,19 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
|
|
||||||
adjust_position(isIncrease)
|
adjust_position(isIncrease)
|
||||||
{
|
{
|
||||||
this.seek_done = false;
|
this.seekDone = false;
|
||||||
|
|
||||||
const { controls } = this.widget.get_ancestor(Gtk.Grid);
|
const { controls } = this.widget.get_ancestor(Gtk.Grid);
|
||||||
const max = controls.positionAdjustment.get_upper();
|
const max = controls.positionAdjustment.get_upper();
|
||||||
const seekingUnit = settings.get_string('seeking-unit');
|
|
||||||
|
|
||||||
let seekingValue = settings.get_int('seeking-value');
|
let seekingValue = settings.get_int('seeking-value');
|
||||||
|
|
||||||
switch(seekingUnit) {
|
switch(settings.get_int('seeking-unit')) {
|
||||||
case 'minute':
|
case 2: /* Percentage */
|
||||||
seekingValue *= 60;
|
seekingValue *= max / 100;
|
||||||
break;
|
break;
|
||||||
case 'percentage':
|
case 1: /* Minute */
|
||||||
seekingValue = max * seekingValue / 100;
|
seekingValue *= 60;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -538,16 +532,15 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
const clapperWidget = player.widget.get_ancestor(Gtk.Grid);
|
const clapperWidget = player.widget.get_ancestor(Gtk.Grid);
|
||||||
if(!clapperWidget) return;
|
if(!clapperWidget) return;
|
||||||
|
|
||||||
if(!this.seek_done && state !== GstClapper.ClapperState.BUFFERING) {
|
if(!this.seekDone && state !== GstClapper.ClapperState.BUFFERING) {
|
||||||
clapperWidget.updateTime();
|
clapperWidget.updateTime();
|
||||||
|
|
||||||
if(this.needsFastSeekRestore) {
|
if(this.needsFastSeekRestore) {
|
||||||
this.set_seek_mode(GstClapper.ClapperSeekMode.FAST);
|
this.set_seek_mode(GstClapper.ClapperSeekMode.FAST);
|
||||||
this.seekingMode = 'fast';
|
|
||||||
this.needsFastSeekRestore = false;
|
this.needsFastSeekRestore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.seek_done = true;
|
this.seekDone = true;
|
||||||
debug('seeking finished');
|
debug('seeking finished');
|
||||||
|
|
||||||
clapperWidget._onPlayerPositionUpdated(this, this.position);
|
clapperWidget._onPlayerPositionUpdated(this, this.position);
|
||||||
@@ -566,7 +559,8 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
if(this.playlistWidget._handleStreamEnded(player))
|
if(this.playlistWidget._handleStreamEnded(player))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(settings.get_boolean('close-auto')) {
|
/* After playback equal 2 means close the app */
|
||||||
|
if(settings.get_int('after-playback') === 2) {
|
||||||
/* Stop will be automatically called soon afterwards */
|
/* Stop will be automatically called soon afterwards */
|
||||||
this.quitOnStop = true;
|
this.quitOnStop = true;
|
||||||
this._performCloseCleanup(this.widget.get_root());
|
this._performCloseCleanup(this.widget.get_root());
|
||||||
@@ -640,16 +634,18 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
let root, value, action;
|
let root, value, action;
|
||||||
|
|
||||||
switch(key) {
|
switch(key) {
|
||||||
|
case 'after-playback':
|
||||||
|
this.widget.keep_last_frame = (settings.get_int(key) === 1);
|
||||||
|
break;
|
||||||
case 'seeking-mode':
|
case 'seeking-mode':
|
||||||
this.seekingMode = settings.get_string('seeking-mode');
|
switch(settings.get_int(key)) {
|
||||||
switch(this.seekingMode) {
|
case 2: /* Fast */
|
||||||
case 'fast':
|
|
||||||
this.set_seek_mode(GstClapper.ClapperSeekMode.FAST);
|
this.set_seek_mode(GstClapper.ClapperSeekMode.FAST);
|
||||||
break;
|
break;
|
||||||
case 'accurate':
|
case 1: /* Accurate */
|
||||||
this.set_seek_mode(GstClapper.ClapperSeekMode.ACCURATE);
|
this.set_seek_mode(GstClapper.ClapperSeekMode.ACCURATE);
|
||||||
break;
|
break;
|
||||||
default:
|
default: /* Normal */
|
||||||
this.set_seek_mode(GstClapper.ClapperSeekMode.DEFAULT);
|
this.set_seek_mode(GstClapper.ClapperSeekMode.DEFAULT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -669,12 +665,12 @@ class ClapperPlayer extends GstClapper.Clapper
|
|||||||
root[action + '_css_class'](gpuClass);
|
root[action + '_css_class'](gpuClass);
|
||||||
break;
|
break;
|
||||||
case 'audio-offset':
|
case 'audio-offset':
|
||||||
value = Math.round(settings.get_double(key) * -Gst.MSECOND);
|
value = Math.round(settings.get_int(key) * -Gst.MSECOND);
|
||||||
this.set_audio_video_offset(value);
|
this.set_audio_video_offset(value);
|
||||||
debug(`set audio-video offset: ${value}`);
|
debug(`set audio-video offset: ${value}`);
|
||||||
break;
|
break;
|
||||||
case 'subtitle-offset':
|
case 'subtitle-offset':
|
||||||
value = Math.round(settings.get_double(key) * -Gst.MSECOND);
|
value = Math.round(settings.get_int(key) * -Gst.MSECOND);
|
||||||
this.set_subtitle_video_offset(value);
|
this.set_subtitle_video_offset(value);
|
||||||
debug(`set subtitle-video offset: ${value}`);
|
debug(`set subtitle-video offset: ${value}`);
|
||||||
break;
|
break;
|
||||||
|
697
src/prefs.js
697
src/prefs.js
@@ -1,7 +1,8 @@
|
|||||||
const { GObject, Gst, Gtk, Pango } = imports.gi;
|
const { Adw, GObject, Gio, Gst, Gtk } = imports.gi;
|
||||||
|
const Debug = imports.src.debug;
|
||||||
const Misc = imports.src.misc;
|
const Misc = imports.src.misc;
|
||||||
const PrefsBase = imports.src.prefsBase;
|
|
||||||
|
|
||||||
|
const { debug } = Debug;
|
||||||
const { settings } = Misc;
|
const { settings } = Misc;
|
||||||
|
|
||||||
/* PlayFlags are not exported through GI */
|
/* PlayFlags are not exported through GI */
|
||||||
@@ -21,334 +22,454 @@ Gst.PlayFlags = {
|
|||||||
FORCE_SW_DECODERS: 4096,
|
FORCE_SW_DECODERS: 4096,
|
||||||
};
|
};
|
||||||
|
|
||||||
var GeneralPage = GObject.registerClass(
|
const widgetOpts = {
|
||||||
class ClapperGeneralPage extends PrefsBase.Grid
|
halign: Gtk.Align.CENTER,
|
||||||
|
valign: Gtk.Align.CENTER,
|
||||||
|
};
|
||||||
|
|
||||||
|
function getCommonProps()
|
||||||
{
|
{
|
||||||
_init()
|
return {
|
||||||
|
'schema-name': GObject.ParamSpec.string(
|
||||||
|
'schema-name',
|
||||||
|
'GSchema setting name',
|
||||||
|
'Name of the setting to bind',
|
||||||
|
GObject.ParamFlags.WRITABLE,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const flags = Gio.SettingsBindFlags.DEFAULT;
|
||||||
|
|
||||||
|
let PrefsActionRow = GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsActionRow',
|
||||||
|
Properties: getCommonProps(),
|
||||||
|
},
|
||||||
|
class ClapperPrefsActionRow extends Adw.ActionRow
|
||||||
|
{
|
||||||
|
_init(widget)
|
||||||
{
|
{
|
||||||
super._init();
|
super._init();
|
||||||
|
|
||||||
this.addTitle('Startup');
|
this._schemaName = null;
|
||||||
this.addCheckButton('Auto enter fullscreen', 'fullscreen-auto');
|
this._bindProp = null;
|
||||||
|
|
||||||
this.addTitle('Volume');
|
this.add_suffix(widget);
|
||||||
const comboBox = this.addComboBoxText('Initial value', [
|
this.set_activatable_widget(widget);
|
||||||
['restore', "Restore"],
|
|
||||||
['custom', "Custom"],
|
|
||||||
], 'volume-initial');
|
|
||||||
const spinButton = this.addSpinButton('Value (percentage)', 0, 200, 'volume-value');
|
|
||||||
this._onVolumeInitialChanged(spinButton, comboBox);
|
|
||||||
comboBox.connect('changed', this._onVolumeInitialChanged.bind(this, spinButton));
|
|
||||||
|
|
||||||
this.addTitle('Finish');
|
|
||||||
this.addCheckButton('Keep showing last frame', 'keep-last-frame');
|
|
||||||
this.addCheckButton('Close after playback', 'close-auto');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onVolumeInitialChanged(spinButton, comboBox)
|
set schema_name(value)
|
||||||
{
|
{
|
||||||
const value = comboBox.get_active_id();
|
this._schemaName = value;
|
||||||
spinButton.set_visible(value === 'custom');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var BehaviourPage = GObject.registerClass(
|
|
||||||
class ClapperBehaviourPage extends PrefsBase.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init();
|
|
||||||
|
|
||||||
this.addTitle('Seeking');
|
|
||||||
this.addComboBoxText('Mode', [
|
|
||||||
['normal', "Normal"],
|
|
||||||
['accurate', "Accurate"],
|
|
||||||
['fast', "Fast"],
|
|
||||||
], 'seeking-mode');
|
|
||||||
this.addComboBoxText('Unit', [
|
|
||||||
['second', "Second"],
|
|
||||||
['minute', "Minute"],
|
|
||||||
['percentage', "Percentage"],
|
|
||||||
], 'seeking-unit');
|
|
||||||
this.addSpinButton('Value', 1, 99, 'seeking-value');
|
|
||||||
|
|
||||||
this.addTitle('Resume');
|
|
||||||
this.addCheckButton('Ask to resume last unfinished video', 'resume-enabled');
|
|
||||||
|
|
||||||
this.addTitle('Floating Mode');
|
|
||||||
this.addCheckButton('Show on all workspaces', 'floating-stick');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var AudioPage = GObject.registerClass(
|
|
||||||
class ClapperAudioPage extends PrefsBase.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init();
|
|
||||||
|
|
||||||
this.addTitle('Synchronization');
|
|
||||||
this.addSpinButton('Offset (milliseconds)', -1000, 1000, 'audio-offset', 25);
|
|
||||||
|
|
||||||
this.addTitle('Processing');
|
|
||||||
this.addPlayFlagCheckButton('Only use native audio formats', Gst.PlayFlags.NATIVE_AUDIO);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var SubtitlesPage = GObject.registerClass(
|
|
||||||
class ClapperSubtitlesPage extends PrefsBase.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init();
|
|
||||||
|
|
||||||
/* FIXME: This should be moved to subtitles popup and displayed only when
|
|
||||||
external subtitles were added for easier customization per video. */
|
|
||||||
//this.addTitle('Synchronization');
|
|
||||||
//this.addSpinButton('Offset (milliseconds)', -5000, 5000, 'subtitle-offset', 25);
|
|
||||||
|
|
||||||
this.addTitle('External Subtitles');
|
|
||||||
this.addFontButton('Default font', 'subtitle-font');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var NetworkPage = GObject.registerClass(
|
|
||||||
class ClapperNetworkPage extends PrefsBase.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init();
|
|
||||||
|
|
||||||
this.addTitle('Client');
|
|
||||||
this.addPlayFlagCheckButton('Progressive download buffering', Gst.PlayFlags.DOWNLOAD);
|
|
||||||
|
|
||||||
this.addTitle('Server');
|
|
||||||
const webServer = this.addCheckButton('Control player remotely', 'webserver-enabled');
|
|
||||||
const serverPort = this.addSpinButton('Listening port', 1024, 65535, 'webserver-port');
|
|
||||||
webServer.bind_property('active', serverPort, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
const webApp = this.addCheckButton('Start built-in web application', 'webapp-enabled');
|
|
||||||
webServer.bind_property('active', webApp, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
const webAppPort = this.addSpinButton('Web application port', 1024, 65535, 'webapp-port');
|
|
||||||
webServer.bind_property('active', webAppPort, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var YouTubePage = GObject.registerClass(
|
|
||||||
class ClapperYouTubePage extends PrefsBase.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init();
|
|
||||||
|
|
||||||
this.addTitle('YouTube');
|
|
||||||
this.addCheckButton('Prefer adaptive streaming', 'yt-adaptive-enabled');
|
|
||||||
this.addComboBoxText('Max quality', [
|
|
||||||
['normal', "Normal"],
|
|
||||||
['hfr', "HFR"],
|
|
||||||
], 'yt-quality-type');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var GStreamerPage = GObject.registerClass(
|
|
||||||
class ClapperGStreamerPage extends PrefsBase.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init();
|
|
||||||
|
|
||||||
this.addTitle('Plugin Ranking');
|
|
||||||
const listStore = new Gtk.ListStore();
|
|
||||||
listStore.set_column_types([
|
|
||||||
GObject.TYPE_BOOLEAN,
|
|
||||||
GObject.TYPE_STRING,
|
|
||||||
GObject.TYPE_STRING,
|
|
||||||
]);
|
|
||||||
const treeView = new Gtk.TreeView({
|
|
||||||
hexpand: true,
|
|
||||||
vexpand: true,
|
|
||||||
enable_search: false,
|
|
||||||
model: listStore,
|
|
||||||
});
|
|
||||||
const treeSelection = treeView.get_selection();
|
|
||||||
|
|
||||||
const apply = new Gtk.TreeViewColumn({
|
|
||||||
title: "Apply",
|
|
||||||
});
|
|
||||||
const name = new Gtk.TreeViewColumn({
|
|
||||||
title: "Plugin",
|
|
||||||
expand: true,
|
|
||||||
});
|
|
||||||
const rank = new Gtk.TreeViewColumn({
|
|
||||||
title: "Rank",
|
|
||||||
min_width: 90,
|
|
||||||
});
|
|
||||||
|
|
||||||
const applyCell = new Gtk.CellRendererToggle();
|
|
||||||
const nameCell = new Gtk.CellRendererText({
|
|
||||||
editable: true,
|
|
||||||
placeholder_text: "Insert plugin name",
|
|
||||||
});
|
|
||||||
const rankCell = new Gtk.CellRendererText({
|
|
||||||
editable: true,
|
|
||||||
weight: Pango.Weight.BOLD,
|
|
||||||
placeholder_text: "Insert plugin rank",
|
|
||||||
});
|
|
||||||
|
|
||||||
apply.pack_start(applyCell, true);
|
|
||||||
name.pack_start(nameCell, true);
|
|
||||||
rank.pack_start(rankCell, true);
|
|
||||||
|
|
||||||
apply.add_attribute(applyCell, 'active', 0);
|
|
||||||
name.add_attribute(nameCell, 'text', 1);
|
|
||||||
rank.add_attribute(rankCell, 'text', 2);
|
|
||||||
|
|
||||||
treeView.insert_column(apply, 0);
|
|
||||||
treeView.insert_column(name, 1);
|
|
||||||
treeView.insert_column(rank, 2);
|
|
||||||
|
|
||||||
const frame = new Gtk.Frame({
|
|
||||||
child: treeView
|
|
||||||
});
|
|
||||||
this.addToGrid(frame);
|
|
||||||
|
|
||||||
const addButton = new Gtk.Button({
|
|
||||||
icon_name: 'list-add-symbolic',
|
|
||||||
halign: Gtk.Align.END,
|
|
||||||
});
|
|
||||||
const removeButton = new Gtk.Button({
|
|
||||||
icon_name: 'list-remove-symbolic',
|
|
||||||
sensitive: false,
|
|
||||||
halign: Gtk.Align.END,
|
|
||||||
});
|
|
||||||
const label = new Gtk.Label({
|
|
||||||
label: 'Changes require player restart',
|
|
||||||
halign: Gtk.Align.START,
|
|
||||||
hexpand: true,
|
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
|
||||||
});
|
|
||||||
const box = new Gtk.Box({
|
|
||||||
orientation: Gtk.Orientation.HORIZONTAL,
|
|
||||||
spacing: 6,
|
|
||||||
hexpand: true,
|
|
||||||
});
|
|
||||||
box.append(label);
|
|
||||||
box.append(removeButton);
|
|
||||||
box.append(addButton);
|
|
||||||
this.addToGrid(box);
|
|
||||||
|
|
||||||
applyCell.connect('toggled', this._onApplyCellEdited.bind(this));
|
|
||||||
nameCell.connect('edited', this._onNameCellEdited.bind(this));
|
|
||||||
rankCell.connect('edited', this._onRankCellEdited.bind(this));
|
|
||||||
addButton.connect('clicked', this._onAddButtonClicked.bind(this, listStore));
|
|
||||||
removeButton.connect('clicked', this._onRemoveButtonClicked.bind(this, listStore));
|
|
||||||
treeSelection.connect('changed', this._onTreeSelectionChanged.bind(this, removeButton));
|
|
||||||
|
|
||||||
this.settingsChangedSignal = settings.connect(
|
|
||||||
'changed::plugin-ranking', this.refreshListStore.bind(this, listStore)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.refreshListStore(listStore);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshListStore(listStore)
|
vfunc_realize()
|
||||||
{
|
{
|
||||||
const data = JSON.parse(settings.get_string('plugin-ranking'));
|
super.vfunc_realize();
|
||||||
listStore.clear();
|
|
||||||
|
|
||||||
for(let plugin of data) {
|
if(this._schemaName && this._bindProp) {
|
||||||
listStore.set(
|
settings.bind(this._schemaName,
|
||||||
listStore.append(),
|
this.activatable_widget, this._bindProp, flags
|
||||||
[0, 1, 2], [
|
|
||||||
plugin.apply || false,
|
|
||||||
plugin.name || '',
|
|
||||||
plugin.rank || 0
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this._schemaName = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let PrefsSubpageRow = GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsSubpageRow',
|
||||||
|
Properties: getCommonProps(),
|
||||||
|
},
|
||||||
|
class ClapperPrefsSubpageRow extends Adw.ActionRow
|
||||||
|
{
|
||||||
|
_init(widget)
|
||||||
|
{
|
||||||
|
super._init({
|
||||||
|
activatable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
this._prefsSubpage = null;
|
||||||
|
|
||||||
|
const icon = new Gtk.Image({
|
||||||
|
icon_name: 'go-next-symbolic',
|
||||||
|
});
|
||||||
|
this.add_suffix(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlugin(index, prop, value)
|
vfunc_activate()
|
||||||
|
{
|
||||||
|
super.vfunc_activate();
|
||||||
|
|
||||||
|
if(!this._prefsSubpage)
|
||||||
|
this._prefsSubpage = this._createSubpage();
|
||||||
|
|
||||||
|
const prefs = this.get_ancestor(PrefsWindow);
|
||||||
|
prefs.present_subpage(this._prefsSubpage);
|
||||||
|
}
|
||||||
|
|
||||||
|
_createSubpage()
|
||||||
|
{
|
||||||
|
/* For override */
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsSwitch',
|
||||||
|
},
|
||||||
|
class ClapperPrefsSwitch extends PrefsActionRow
|
||||||
|
{
|
||||||
|
_init()
|
||||||
|
{
|
||||||
|
super._init(new Gtk.Switch(widgetOpts));
|
||||||
|
this._bindProp = 'active';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsPlayFlagSwitch',
|
||||||
|
Properties: {
|
||||||
|
'play-flag': GObject.ParamSpec.int(
|
||||||
|
'play-flag',
|
||||||
|
'PlayFlag',
|
||||||
|
'Value of the gstreamer play flag to toggle',
|
||||||
|
GObject.ParamFlags.WRITABLE,
|
||||||
|
1, 4096, 1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
class ClapperPrefsPlayFlagSwitch extends PrefsActionRow
|
||||||
|
{
|
||||||
|
_init()
|
||||||
|
{
|
||||||
|
super._init(new Gtk.Switch(widgetOpts));
|
||||||
|
|
||||||
|
this._flag = 1;
|
||||||
|
this._doneRealize = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
set play_flag(value)
|
||||||
|
{
|
||||||
|
this._flag = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_realize()
|
||||||
|
{
|
||||||
|
super.vfunc_realize();
|
||||||
|
|
||||||
|
if(!this._doneRealize) {
|
||||||
|
const playFlags = settings.get_int('play-flags');
|
||||||
|
|
||||||
|
this.activatable_widget.active = (
|
||||||
|
(playFlags & this._flag) === this._flag
|
||||||
|
);
|
||||||
|
this.activatable_widget.connect(
|
||||||
|
'notify::active', this._onPlayFlagToggled.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this._doneRealize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPlayFlagToggled()
|
||||||
|
{
|
||||||
|
let playFlags = settings.get_int('play-flags');
|
||||||
|
|
||||||
|
if(this.activatable_widget.active)
|
||||||
|
playFlags |= this._flag;
|
||||||
|
else
|
||||||
|
playFlags &= ~this._flag;
|
||||||
|
|
||||||
|
settings.set_int('play-flags', playFlags);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsSpin',
|
||||||
|
Properties: {
|
||||||
|
'spin-adjustment': GObject.ParamSpec.object(
|
||||||
|
'spin-adjustment',
|
||||||
|
'GtkAdjustment',
|
||||||
|
'Custom GtkAdjustment for spin button',
|
||||||
|
GObject.ParamFlags.WRITABLE,
|
||||||
|
Gtk.Adjustment
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
class ClapperPrefsSpin extends PrefsActionRow
|
||||||
|
{
|
||||||
|
_init()
|
||||||
|
{
|
||||||
|
super._init(new Gtk.SpinButton(widgetOpts));
|
||||||
|
this._bindProp = 'value';
|
||||||
|
}
|
||||||
|
|
||||||
|
set spin_adjustment(value)
|
||||||
|
{
|
||||||
|
this.activatable_widget.set_adjustment(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let PrefsPluginFeature = GObject.registerClass(
|
||||||
|
class PrefsPluginFeature extends Adw.ActionRow
|
||||||
|
{
|
||||||
|
_init(featureObj)
|
||||||
|
{
|
||||||
|
super._init({
|
||||||
|
title: featureObj.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
const enableSwitch = new Gtk.Switch(widgetOpts);
|
||||||
|
const spinButton = new Gtk.SpinButton(widgetOpts);
|
||||||
|
|
||||||
|
spinButton.set_range(0, 512);
|
||||||
|
spinButton.set_increments(1, 1);
|
||||||
|
|
||||||
|
enableSwitch.active = featureObj.enabled;
|
||||||
|
spinButton.value = featureObj.rank;
|
||||||
|
this.currentRank = featureObj.rank;
|
||||||
|
|
||||||
|
this.add_suffix(enableSwitch);
|
||||||
|
this.add_suffix(spinButton);
|
||||||
|
|
||||||
|
enableSwitch.bind_property('active', spinButton, 'sensitive',
|
||||||
|
GObject.BindingFlags.SYNC_CREATE
|
||||||
|
);
|
||||||
|
|
||||||
|
enableSwitch.connect('notify::active', this._onSwitchActivate.bind(this));
|
||||||
|
spinButton.connect('value-changed', this._onValueChanged.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateRanking(data)
|
||||||
{
|
{
|
||||||
const data = JSON.parse(settings.get_string('plugin-ranking'));
|
|
||||||
data[index][prop] = value;
|
|
||||||
settings.set_string('plugin-ranking', JSON.stringify(data));
|
settings.set_string('plugin-ranking', JSON.stringify(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTreeSelectionChanged(removeButton, treeSelection)
|
_onSwitchActivate(enableSwitch)
|
||||||
{
|
{
|
||||||
const [isSelected, model, iter] = treeSelection.get_selected();
|
const { settingsData } = this.get_ancestor(PrefsPluginRankingSubpage);
|
||||||
this.activeIndex = -1;
|
|
||||||
|
|
||||||
if(isSelected) {
|
if(enableSwitch.active)
|
||||||
this.activeIndex = Number(model.get_string_from_iter(iter));
|
settingsData[this.title] = this.currentRank;
|
||||||
|
else if(settingsData[this.title])
|
||||||
|
delete settingsData[this.title];
|
||||||
|
|
||||||
|
this._updateRanking(settingsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeButton.set_sensitive(this.activeIndex >= 0);
|
_onValueChanged(spinButton)
|
||||||
}
|
|
||||||
|
|
||||||
_onAddButtonClicked(listStore, button)
|
|
||||||
{
|
{
|
||||||
const data = JSON.parse(settings.get_string('plugin-ranking'));
|
const { settingsData } = this.get_ancestor(PrefsPluginRankingSubpage);
|
||||||
data.push({
|
|
||||||
apply: false,
|
this.currentRank = spinButton.value;
|
||||||
name: '',
|
settingsData[this.title] = this.currentRank;
|
||||||
rank: 0,
|
|
||||||
|
this._updateRanking(settingsData);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
settings.set_string('plugin-ranking', JSON.stringify(data));
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsFont',
|
||||||
|
},
|
||||||
|
class ClapperPrefsFont extends PrefsActionRow
|
||||||
|
{
|
||||||
|
_init()
|
||||||
|
{
|
||||||
|
const opts = {
|
||||||
|
use_font: true,
|
||||||
|
use_size: true,
|
||||||
|
};
|
||||||
|
Object.assign(opts, widgetOpts);
|
||||||
|
|
||||||
|
super._init(new Gtk.FontButton(opts));
|
||||||
|
this._bindProp = 'font';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsCombo',
|
||||||
|
Properties: getCommonProps(),
|
||||||
|
},
|
||||||
|
class ClapperPrefsCombo extends Adw.ComboRow
|
||||||
|
{
|
||||||
|
_init()
|
||||||
|
{
|
||||||
|
super._init();
|
||||||
|
this._schemaName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRemoveButtonClicked(listStore, button)
|
set schema_name(value)
|
||||||
{
|
{
|
||||||
if(this.activeIndex < 0)
|
this._schemaName = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_realize()
|
||||||
|
{
|
||||||
|
super.vfunc_realize();
|
||||||
|
|
||||||
|
if(this._schemaName)
|
||||||
|
settings.bind(this._schemaName, this, 'selected', flags);
|
||||||
|
|
||||||
|
this._schemaName = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsExpander',
|
||||||
|
Properties: getCommonProps(),
|
||||||
|
},
|
||||||
|
class ClapperPrefsExpander extends Adw.ExpanderRow
|
||||||
|
{
|
||||||
|
_init()
|
||||||
|
{
|
||||||
|
super._init({
|
||||||
|
show_enable_switch: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
set schema_name(value)
|
||||||
|
{
|
||||||
|
settings.bind(value, this, 'enable-expansion', flags);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsPluginRankingSubpageRow',
|
||||||
|
},
|
||||||
|
class ClapperPrefsPluginRankingSubpageRow extends PrefsSubpageRow
|
||||||
|
{
|
||||||
|
_createSubpage()
|
||||||
|
{
|
||||||
|
return new PrefsPluginRankingSubpage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let PrefsPluginExpander = GObject.registerClass(
|
||||||
|
class ClapperPrefsPluginExpander extends Adw.ExpanderRow
|
||||||
|
{
|
||||||
|
_init(plugin)
|
||||||
|
{
|
||||||
|
super._init({
|
||||||
|
title: plugin,
|
||||||
|
show_enable_switch: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expandSignal = this.connect(
|
||||||
|
'notify::expanded', this._onExpandedNotify.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onExpandedNotify()
|
||||||
|
{
|
||||||
|
if(!this.expanded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const data = JSON.parse(settings.get_string('plugin-ranking'));
|
this.disconnect(this.expandSignal);
|
||||||
data.splice(this.activeIndex, 1);
|
this.expandSignal = null;
|
||||||
settings.set_string('plugin-ranking', JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onApplyCellEdited(cell, path)
|
const { pluginsData } = this.get_ancestor(PrefsPluginRankingSubpage);
|
||||||
{
|
|
||||||
const newState = !cell.active;
|
|
||||||
this.updatePlugin(path, 'apply', newState);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onNameCellEdited(cell, path, newText)
|
pluginsData[this.title].sort((a, b) =>
|
||||||
{
|
(a.name > b.name) - (a.name < b.name)
|
||||||
newText = newText.trim();
|
);
|
||||||
this.updatePlugin(path, 'name', newText);
|
const featuresNames = Object.keys(pluginsData[this.title]);
|
||||||
}
|
debug(`Adding ${featuresNames.length} features to the list of plugin: ${this.title}`);
|
||||||
|
|
||||||
_onRankCellEdited(cell, path, newText)
|
for(let featureObj of pluginsData[this.title])
|
||||||
{
|
this.add(new PrefsPluginFeature(featureObj));
|
||||||
newText = newText.trim();
|
|
||||||
|
|
||||||
if(isNaN(newText))
|
|
||||||
newText = 0;
|
|
||||||
|
|
||||||
this.updatePlugin(path, 'rank', Number(newText));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onClose()
|
|
||||||
{
|
|
||||||
super._onClose('gstreamer');
|
|
||||||
|
|
||||||
settings.disconnect(this.settingsChangedSignal);
|
|
||||||
this.settingsChangedSignal = null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var TweaksPage = GObject.registerClass(
|
let PrefsPluginRankingSubpage = GObject.registerClass({
|
||||||
class ClapperTweaksPage extends PrefsBase.Grid
|
GTypeName: 'ClapperPrefsPluginRankingSubpage',
|
||||||
|
Template: `file://${Misc.getClapperPath()}/ui/preferences-plugin-ranking-subpage.ui`,
|
||||||
|
InternalChildren: ['decoders_group'],
|
||||||
|
},
|
||||||
|
class ClapperPrefsPluginRankingSubpage extends Gtk.Box
|
||||||
{
|
{
|
||||||
_init()
|
_init()
|
||||||
{
|
{
|
||||||
super._init();
|
super._init();
|
||||||
|
|
||||||
this.addTitle('Appearance');
|
if(!Gst.is_initialized())
|
||||||
this.addCheckButton('Enable dark theme', 'dark-theme');
|
Gst.init(null);
|
||||||
|
|
||||||
this.addTitle('Performance');
|
const gstRegistry = Gst.Registry.get();
|
||||||
this.addCheckButton('Render window shadows', 'render-shadows');
|
const decoders = gstRegistry.feature_filter(this._decodersFilterCb, false);
|
||||||
|
|
||||||
|
const plugins = {};
|
||||||
|
this.settingsData = {};
|
||||||
|
|
||||||
|
/* In case someone messed up gsettings values */
|
||||||
|
try {
|
||||||
|
this.settingsData = JSON.parse(settings.get_string('plugin-ranking'));
|
||||||
|
/* Might be an array in older Clapper versions */
|
||||||
|
if(Array.isArray(this.settingsData))
|
||||||
|
this.settingsData = {};
|
||||||
|
}
|
||||||
|
catch(err) { /* Ignore */ }
|
||||||
|
|
||||||
|
for(let decoder of decoders) {
|
||||||
|
const pluginName = decoder.get_plugin_name();
|
||||||
|
|
||||||
|
/* Do not add unsupported plugins */
|
||||||
|
switch(pluginName) {
|
||||||
|
case 'playback':
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!plugins[pluginName])
|
||||||
|
plugins[pluginName] = [];
|
||||||
|
|
||||||
|
const decName = decoder.get_name();
|
||||||
|
|
||||||
|
plugins[pluginName].push({
|
||||||
|
name: decName,
|
||||||
|
rank: decoder.get_rank(),
|
||||||
|
enabled: this.settingsData[decName] != null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const pluginsNames = Object.keys(plugins);
|
||||||
|
debug(`Adding ${pluginsNames.length} found plugins to the list`);
|
||||||
|
|
||||||
|
this.pluginsData = pluginsNames.sort().reduce((res, key) =>
|
||||||
|
(res[key] = plugins[key], res), {}
|
||||||
|
);
|
||||||
|
|
||||||
|
for(let plugin in this.pluginsData)
|
||||||
|
this._decoders_group.add(new PrefsPluginExpander(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
_decodersFilterCb(feature)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
feature.list_is_type
|
||||||
|
&& feature.list_is_type(Gst.ELEMENT_FACTORY_TYPE_DECODER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onReturnClicked(button)
|
||||||
|
{
|
||||||
|
const prefs = this.get_ancestor(PrefsWindow);
|
||||||
|
prefs.close_subpage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var PrefsWindow = GObject.registerClass({
|
||||||
|
GTypeName: 'ClapperPrefsWindow',
|
||||||
|
Template: `file://${Misc.getClapperPath()}/ui/preferences-window.ui`,
|
||||||
|
},
|
||||||
|
class ClapperPrefsWindow extends Adw.PreferencesWindow
|
||||||
|
{
|
||||||
|
_init(window)
|
||||||
|
{
|
||||||
|
super._init({
|
||||||
|
transient_for: window,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
238
src/prefsBase.js
238
src/prefsBase.js
@@ -1,238 +0,0 @@
|
|||||||
const { Gio, GObject, Gtk } = imports.gi;
|
|
||||||
const Debug = imports.src.debug;
|
|
||||||
const Misc = imports.src.misc;
|
|
||||||
|
|
||||||
const { debug } = Debug;
|
|
||||||
const { settings } = Misc;
|
|
||||||
|
|
||||||
var Notebook = GObject.registerClass(
|
|
||||||
class ClapperPrefsNotebook extends Gtk.Notebook
|
|
||||||
{
|
|
||||||
_init(pages, isSubpage)
|
|
||||||
{
|
|
||||||
super._init({
|
|
||||||
show_border: false,
|
|
||||||
vexpand: true,
|
|
||||||
hexpand: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if(isSubpage) {
|
|
||||||
this.set_tab_pos(Gtk.PositionType.LEFT);
|
|
||||||
this.add_css_class('prefssubpage');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addArrayPages(pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
addArrayPages(array)
|
|
||||||
{
|
|
||||||
for(let obj of array)
|
|
||||||
this.addObjectPages(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
addObjectPages(item)
|
|
||||||
{
|
|
||||||
const widget = (item.pages)
|
|
||||||
? new Notebook(item.pages, true)
|
|
||||||
: new item.widget();
|
|
||||||
|
|
||||||
this.addToNotebook(widget, item.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
addToNotebook(widget, title)
|
|
||||||
{
|
|
||||||
const label = new Gtk.Label({
|
|
||||||
label: title,
|
|
||||||
});
|
|
||||||
this.append_page(widget, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onClose()
|
|
||||||
{
|
|
||||||
const totalPages = this.get_n_pages();
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
while(index < totalPages) {
|
|
||||||
const page = this.get_nth_page(index);
|
|
||||||
page._onClose();
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var Grid = GObject.registerClass(
|
|
||||||
class ClapperPrefsGrid extends Gtk.Grid
|
|
||||||
{
|
|
||||||
_init()
|
|
||||||
{
|
|
||||||
super._init({
|
|
||||||
row_spacing: 6,
|
|
||||||
column_spacing: 20,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.flag = Gio.SettingsBindFlags.DEFAULT;
|
|
||||||
this.gridIndex = 0;
|
|
||||||
this.widgetDefaults = {
|
|
||||||
width_request: 160,
|
|
||||||
halign: Gtk.Align.END,
|
|
||||||
valign: Gtk.Align.CENTER,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
addToGrid(leftWidget, rightWidget)
|
|
||||||
{
|
|
||||||
let spanWidth = 2;
|
|
||||||
|
|
||||||
if(rightWidget) {
|
|
||||||
spanWidth = 1;
|
|
||||||
rightWidget.bind_property('visible', leftWidget, 'visible',
|
|
||||||
GObject.BindingFlags.SYNC_CREATE
|
|
||||||
);
|
|
||||||
this.attach(rightWidget, 1, this.gridIndex, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.attach(leftWidget, 0, this.gridIndex, spanWidth, 1);
|
|
||||||
this.gridIndex++;
|
|
||||||
|
|
||||||
return rightWidget || leftWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
addTitle(text)
|
|
||||||
{
|
|
||||||
const label = this.getLabel(text, true);
|
|
||||||
|
|
||||||
return this.addToGrid(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
addComboBoxText(text, entries, setting)
|
|
||||||
{
|
|
||||||
const label = this.getLabel(text + ':');
|
|
||||||
const widget = this.getComboBoxText(entries, setting);
|
|
||||||
|
|
||||||
return this.addToGrid(label, widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
addSpinButton(text, min, max, setting, precision)
|
|
||||||
{
|
|
||||||
const label = this.getLabel(text + ':');
|
|
||||||
const widget = this.getSpinButton(min, max, setting, precision);
|
|
||||||
|
|
||||||
return this.addToGrid(label, widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
addCheckButton(text, setting)
|
|
||||||
{
|
|
||||||
const widget = this.getCheckButton(text, setting);
|
|
||||||
|
|
||||||
return this.addToGrid(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
addPlayFlagCheckButton(text, flag)
|
|
||||||
{
|
|
||||||
const checkButton = this.addCheckButton(text);
|
|
||||||
const playFlags = settings.get_int('play-flags');
|
|
||||||
|
|
||||||
checkButton.active = ((playFlags & flag) === flag);
|
|
||||||
checkButton.connect('toggled', this._onPlayFlagToggled.bind(this, flag));
|
|
||||||
|
|
||||||
return checkButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
addFontButton(text, setting)
|
|
||||||
{
|
|
||||||
const label = this.getLabel(text + ':');
|
|
||||||
const widget = this.getFontButton(setting);
|
|
||||||
|
|
||||||
return this.addToGrid(label, widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
getLabel(text, isTitle)
|
|
||||||
{
|
|
||||||
const marginTop = (isTitle && this.gridIndex > 0) ? 16 : 0;
|
|
||||||
const marginBottom = (isTitle) ? 2 : 0;
|
|
||||||
|
|
||||||
let marginLR = 0;
|
|
||||||
|
|
||||||
if(isTitle)
|
|
||||||
text = '<span font="12"><b>' + text + '</b></span>';
|
|
||||||
else
|
|
||||||
marginLR = 12;
|
|
||||||
|
|
||||||
return new Gtk.Label({
|
|
||||||
label: text,
|
|
||||||
use_markup: true,
|
|
||||||
hexpand: true,
|
|
||||||
halign: Gtk.Align.START,
|
|
||||||
margin_top: marginTop,
|
|
||||||
margin_bottom: marginBottom,
|
|
||||||
margin_start: marginLR,
|
|
||||||
margin_end: marginLR,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getComboBoxText(entries, setting)
|
|
||||||
{
|
|
||||||
const comboBox = new Gtk.ComboBoxText(this.widgetDefaults);
|
|
||||||
|
|
||||||
for(let entry of entries)
|
|
||||||
comboBox.append(entry[0], entry[1]);
|
|
||||||
|
|
||||||
settings.bind(setting, comboBox, 'active-id', this.flag);
|
|
||||||
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSpinButton(min, max, setting, precision)
|
|
||||||
{
|
|
||||||
precision = precision || 1;
|
|
||||||
|
|
||||||
const spinButton = new Gtk.SpinButton(this.widgetDefaults);
|
|
||||||
spinButton.set_range(min, max);
|
|
||||||
spinButton.set_digits(precision % 1 === 0 ? 0 : 3);
|
|
||||||
spinButton.set_increments(precision, 1);
|
|
||||||
settings.bind(setting, spinButton, 'value', this.flag);
|
|
||||||
|
|
||||||
return spinButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCheckButton(text, setting)
|
|
||||||
{
|
|
||||||
const checkButton = new Gtk.CheckButton({
|
|
||||||
label: text || null,
|
|
||||||
});
|
|
||||||
|
|
||||||
if(setting)
|
|
||||||
settings.bind(setting, checkButton, 'active', this.flag);
|
|
||||||
|
|
||||||
return checkButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
getFontButton(setting)
|
|
||||||
{
|
|
||||||
const fontButton = new Gtk.FontButton({
|
|
||||||
use_font: true,
|
|
||||||
use_size: true,
|
|
||||||
});
|
|
||||||
settings.bind(setting, fontButton, 'font', this.flag);
|
|
||||||
|
|
||||||
return fontButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPlayFlagToggled(flag, button)
|
|
||||||
{
|
|
||||||
let playFlags = settings.get_int('play-flags');
|
|
||||||
|
|
||||||
if(button.active)
|
|
||||||
playFlags |= flag;
|
|
||||||
else
|
|
||||||
playFlags &= ~flag;
|
|
||||||
|
|
||||||
settings.set_int('play-flags', playFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onClose(name)
|
|
||||||
{
|
|
||||||
if(name)
|
|
||||||
debug(`cleanup of prefs ${name} page`);
|
|
||||||
}
|
|
||||||
});
|
|
@@ -492,7 +492,7 @@ class ClapperWidget extends Gtk.Grid
|
|||||||
if(
|
if(
|
||||||
!this.isSeekable
|
!this.isSeekable
|
||||||
|| this.controls.isPositionDragging
|
|| this.controls.isPositionDragging
|
||||||
|| !player.seek_done
|
|| !player.seekDone
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -317,7 +317,7 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
width: monitor.geometry.width * monitor.scale_factor,
|
width: monitor.geometry.width * monitor.scale_factor,
|
||||||
height: monitor.geometry.height * monitor.scale_factor,
|
height: monitor.geometry.height * monitor.scale_factor,
|
||||||
codec: 'h264',
|
codec: 'h264',
|
||||||
type: settings.get_string('yt-quality-type'),
|
type: YTItags.QualityType[settings.get_int('yt-quality-type')],
|
||||||
adaptive: settings.get_boolean('yt-adaptive-enabled'),
|
adaptive: settings.get_boolean('yt-adaptive-enabled'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
var QualityType = {
|
||||||
|
0: 'normal',
|
||||||
|
1: 'hfr',
|
||||||
|
};
|
||||||
|
|
||||||
const Itags = {
|
const Itags = {
|
||||||
video: {
|
video: {
|
||||||
h264: {
|
h264: {
|
||||||
|
30
ui/preferences-plugin-ranking-subpage.ui
Normal file
30
ui/preferences-plugin-ranking-subpage.ui
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="ClapperPrefsPluginRankingSubpage" parent="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup" id="decoders_group">
|
||||||
|
<property name="title" translatable="yes">Decoders</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton">
|
||||||
|
<property name="label" translatable="yes">Return to the preferences</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="margin_top">12</property>
|
||||||
|
<property name="margin_bottom">12</property>
|
||||||
|
<signal name="clicked" handler="_onReturnClicked"/>
|
||||||
|
<style>
|
||||||
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
292
ui/preferences-window.ui
Normal file
292
ui/preferences-window.ui
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="ClapperPrefsWindow" parent="AdwPreferencesWindow">
|
||||||
|
<property name="title" translatable="yes">Preferences</property>
|
||||||
|
<property name="resizable">True</property>
|
||||||
|
<property name="search-enabled">True</property>
|
||||||
|
<property name="destroy-with-parent">True</property>
|
||||||
|
<property name="can-swipe-back">True</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<property name="title" translatable="yes">General</property>
|
||||||
|
<property name="icon-name">user-home-symbolic</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Behavior</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Auto fullscreen</property>
|
||||||
|
<property name="subtitle" translatable="yes">Enter fullscreen when playlist is replaced except floating mode</property>
|
||||||
|
<property name="schema-name">fullscreen-auto</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Ask to resume recent media</property>
|
||||||
|
<property name="schema-name">resume-enabled</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Float on all workspaces</property>
|
||||||
|
<property name="subtitle" translatable="yes">This option only works on GNOME</property>
|
||||||
|
<property name="schema-name">floating-stick</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsCombo">
|
||||||
|
<property name="title" translatable="yes">After playback</property>
|
||||||
|
<property name="schema-name">after-playback</property>
|
||||||
|
<property name="model">
|
||||||
|
<object class="GtkStringList">
|
||||||
|
<items>
|
||||||
|
<item translatable="yes">Do nothing</item>
|
||||||
|
<item translatable="yes">Freeze last frame</item>
|
||||||
|
<item translatable="yes">Close the app</item>
|
||||||
|
</items>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Volume</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsExpander">
|
||||||
|
<property name="title" translatable="yes">Custom initial value</property>
|
||||||
|
<property name="subtitle" translatable="yes">Set custom volume at startup instead of restoring it</property>
|
||||||
|
<property name="schema-name">volume-custom</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSpin">
|
||||||
|
<property name="title" translatable="yes">Volume percentage</property>
|
||||||
|
<property name="schema-name">volume-value</property>
|
||||||
|
<property name="spin-adjustment">volume_adjustment</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Seeking</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsCombo">
|
||||||
|
<property name="title" translatable="yes">Mode</property>
|
||||||
|
<property name="schema-name">seeking-mode</property>
|
||||||
|
<property name="model">
|
||||||
|
<object class="GtkStringList">
|
||||||
|
<items>
|
||||||
|
<item translatable="yes">Normal</item>
|
||||||
|
<item translatable="yes">Accurate</item>
|
||||||
|
<item translatable="yes">Fast</item>
|
||||||
|
</items>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsCombo">
|
||||||
|
<property name="title" translatable="yes">Unit</property>
|
||||||
|
<property name="schema-name">seeking-unit</property>
|
||||||
|
<property name="model">
|
||||||
|
<object class="GtkStringList">
|
||||||
|
<items>
|
||||||
|
<item translatable="yes">Second</item>
|
||||||
|
<item translatable="yes">Minute</item>
|
||||||
|
<item translatable="yes">Percentage</item>
|
||||||
|
</items>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSpin">
|
||||||
|
<property name="title" translatable="yes">Value</property>
|
||||||
|
<property name="schema-name">seeking-value</property>
|
||||||
|
<property name="spin-adjustment">seeking_adjustment</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<property name="title" translatable="yes">Playback</property>
|
||||||
|
<property name="icon-name">camera-video-symbolic</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Audio</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSpin">
|
||||||
|
<property name="title" translatable="yes">Offset in milliseconds</property>
|
||||||
|
<property name="schema-name">audio-offset</property>
|
||||||
|
<property name="spin-adjustment">audio_offset_adjustment</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsPlayFlagSwitch">
|
||||||
|
<property name="title" translatable="yes">Only native audio formats</property>
|
||||||
|
<property name="play-flag">32</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Subtitles</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsFont">
|
||||||
|
<property name="title" translatable="yes">Default font</property>
|
||||||
|
<property name="schema-name">subtitle-font</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<property name="title" translatable="yes">Network</property>
|
||||||
|
<property name="icon-name">preferences-system-network-symbolic</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Client</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsPlayFlagSwitch">
|
||||||
|
<property name="title" translatable="yes">Progressive download buffering</property>
|
||||||
|
<property name="play-flag">128</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Server</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsExpander">
|
||||||
|
<property name="title" translatable="yes">Control player remotely</property>
|
||||||
|
<property name="schema-name">webserver-enabled</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSpin">
|
||||||
|
<property name="title" translatable="yes">Listening port</property>
|
||||||
|
<property name="schema-name">webserver-port</property>
|
||||||
|
<property name="spin-adjustment">web_server_adjustment</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Run web application in background</property>
|
||||||
|
<property name="subtitle" translatable="yes">Requires GTK compiled with Broadway backend</property>
|
||||||
|
<property name="schema-name">webapp-enabled</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSpin">
|
||||||
|
<property name="title" translatable="yes">Web application port</property>
|
||||||
|
<property name="schema-name">webapp-port</property>
|
||||||
|
<property name="spin-adjustment">web_app_adjustment</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">YouTube</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Prefer adaptive streaming</property>
|
||||||
|
<property name="schema-name">yt-adaptive-enabled</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsCombo">
|
||||||
|
<property name="title" translatable="yes">Max quality</property>
|
||||||
|
<property name="schema-name">yt-quality-type</property>
|
||||||
|
<property name="model">
|
||||||
|
<object class="GtkStringList">
|
||||||
|
<items>
|
||||||
|
<item translatable="yes">Normal</item>
|
||||||
|
<item translatable="no">HFR</item>
|
||||||
|
</items>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<property name="title" translatable="yes">Tweaks</property>
|
||||||
|
<property name="icon-name">applications-engineering-symbolic</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Appearance</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Dark theme</property>
|
||||||
|
<property name="schema-name">dark-theme</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsSwitch">
|
||||||
|
<property name="title" translatable="yes">Render window shadows</property>
|
||||||
|
<property name="subtitle" translatable="yes">Disable to increase performance when windowed</property>
|
||||||
|
<property name="schema-name">render-shadows</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">GStreamer</property>
|
||||||
|
<child>
|
||||||
|
<object class="ClapperPrefsPluginRankingSubpageRow">
|
||||||
|
<property name="title" translatable="yes">Plugin ranking</property>
|
||||||
|
<property name="subtitle" translatable="yes">Alter default ranks of GStreamer plugins</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
<object class="GtkAdjustment" id="seeking_adjustment">
|
||||||
|
<property name="lower">0</property>
|
||||||
|
<property name="upper">99</property>
|
||||||
|
<property name="step-increment">1</property>
|
||||||
|
<property name="page-increment">1</property>
|
||||||
|
</object>
|
||||||
|
<object class="GtkAdjustment" id="volume_adjustment">
|
||||||
|
<property name="lower">0</property>
|
||||||
|
<property name="upper">150</property>
|
||||||
|
<property name="step-increment">1</property>
|
||||||
|
<property name="page-increment">1</property>
|
||||||
|
</object>
|
||||||
|
<object class="GtkAdjustment" id="audio_offset_adjustment">
|
||||||
|
<property name="lower">-1000</property>
|
||||||
|
<property name="upper">1000</property>
|
||||||
|
<property name="step-increment">25</property>
|
||||||
|
<property name="page-increment">1</property>
|
||||||
|
</object>
|
||||||
|
<object class="GtkAdjustment" id="web_server_adjustment">
|
||||||
|
<property name="lower">1024</property>
|
||||||
|
<property name="upper">65535</property>
|
||||||
|
<property name="step-increment">1</property>
|
||||||
|
<property name="page-increment">1</property>
|
||||||
|
</object>
|
||||||
|
<object class="GtkAdjustment" id="web_app_adjustment">
|
||||||
|
<property name="lower">1024</property>
|
||||||
|
<property name="upper">65535</property>
|
||||||
|
<property name="step-increment">1</property>
|
||||||
|
<property name="page-increment">1</property>
|
||||||
|
</object>
|
||||||
|
</interface>
|
Reference in New Issue
Block a user