mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 07:42:23 +02:00
Initial GTK4 port
Port most of the player to GTK4. Some things are still broken or disabled due to GTK change, but will be gradually fixed.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
const { Gdk, GLib, GObject, Gtk, GstPlayer } = imports.gi;
|
const { Gdk, GLib, GObject, Gtk, GstPlayer } = imports.gi;
|
||||||
const Debug = imports.clapper_src.debug;
|
const Debug = imports.clapper_src.debug;
|
||||||
|
const { HeaderBar } = imports.clapper_src.headerbar;
|
||||||
const { Interface } = imports.clapper_src.interface;
|
const { Interface } = imports.clapper_src.interface;
|
||||||
const { Player } = imports.clapper_src.player;
|
const { Player } = imports.clapper_src.player;
|
||||||
const { Window } = imports.clapper_src.window;
|
const { Window } = imports.clapper_src.window;
|
||||||
@@ -47,24 +48,31 @@ var App = GObject.registerClass({
|
|||||||
super.vfunc_startup();
|
super.vfunc_startup();
|
||||||
this.window = new Window(this, APP_NAME);
|
this.window = new Window(this, APP_NAME);
|
||||||
|
|
||||||
|
this.window.connect('close-request', this._onWindowCloseRequest.bind(this));
|
||||||
|
this.window.connect('unmap', () => this.quit());
|
||||||
|
|
||||||
this.windowRealizeSignal = this.window.connect(
|
this.windowRealizeSignal = this.window.connect(
|
||||||
'realize', this._onWindowRealize.bind(this)
|
'realize', this._onWindowRealize.bind(this)
|
||||||
);
|
);
|
||||||
|
/*
|
||||||
this.window.connect(
|
this.window.connect(
|
||||||
'key-press-event', this._onWindowKeyPressEvent.bind(this)
|
'key-press-event', this._onWindowKeyPressEvent.bind(this)
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
this.window.connect(
|
this.window.connect(
|
||||||
'fullscreen-changed', this._onWindowFullscreenChanged.bind(this)
|
'fullscreen-changed', this._onWindowFullscreenChanged.bind(this)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.interface = new Interface();
|
this.interface = new Interface();
|
||||||
let headerBar = new Gtk.HeaderBar({
|
|
||||||
title: APP_NAME,
|
let headerStart = [];
|
||||||
show_close_button: true,
|
let headerEnd = [
|
||||||
});
|
this.interface.controls.openMenuButton,
|
||||||
headerBar.pack_end(this.interface.controls.openMenuButton);
|
this.interface.controls.fullscreenButton
|
||||||
headerBar.pack_end(this.interface.controls.fullscreenButton);
|
];
|
||||||
|
let headerBar = new HeaderBar(this.window, headerStart, headerEnd);
|
||||||
this.interface.addHeaderBar(headerBar, APP_NAME);
|
this.interface.addHeaderBar(headerBar, APP_NAME);
|
||||||
|
|
||||||
this.interface.controls.fullscreenButton.connect(
|
this.interface.controls.fullscreenButton.connect(
|
||||||
'clicked', () => this._onInterfaceToggleFullscreenClicked(true)
|
'clicked', () => this._onInterfaceToggleFullscreenClicked(true)
|
||||||
);
|
);
|
||||||
@@ -73,13 +81,19 @@ var App = GObject.registerClass({
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.window.set_titlebar(this.interface.headerBar);
|
this.window.set_titlebar(this.interface.headerBar);
|
||||||
this.window.add(this.interface);
|
this.window.set_child(this.interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
vfunc_activate()
|
vfunc_activate()
|
||||||
{
|
{
|
||||||
super.vfunc_activate();
|
super.vfunc_activate();
|
||||||
this.window.show_all();
|
|
||||||
|
this.window.show();
|
||||||
|
Gtk.StyleContext.add_provider_for_display(
|
||||||
|
Gdk.Display.get_default(),
|
||||||
|
this.cssProvider,
|
||||||
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(arr)
|
run(arr)
|
||||||
@@ -146,24 +160,23 @@ var App = GObject.registerClass({
|
|||||||
{
|
{
|
||||||
this.window.disconnect(this.windowRealizeSignal);
|
this.window.disconnect(this.windowRealizeSignal);
|
||||||
|
|
||||||
Gtk.StyleContext.add_provider_for_screen(
|
|
||||||
Gdk.Screen.get_default(),
|
|
||||||
this.cssProvider,
|
|
||||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
||||||
);
|
|
||||||
|
|
||||||
this.player = new Player();
|
this.player = new Player();
|
||||||
|
|
||||||
|
if(!this.player.widget)
|
||||||
|
return this.quit();
|
||||||
|
/*
|
||||||
this.player.widget.add_events(
|
this.player.widget.add_events(
|
||||||
Gdk.EventMask.SCROLL_MASK
|
Gdk.EventMask.SCROLL_MASK
|
||||||
| Gdk.EventMask.ENTER_NOTIFY_MASK
|
| Gdk.EventMask.ENTER_NOTIFY_MASK
|
||||||
| Gdk.EventMask.LEAVE_NOTIFY_MASK
|
| Gdk.EventMask.LEAVE_NOTIFY_MASK
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
this.interface.addPlayer(this.player);
|
this.interface.addPlayer(this.player);
|
||||||
|
|
||||||
this.player.connect('warning', this._onPlayerWarning.bind(this));
|
this.player.connect('warning', this._onPlayerWarning.bind(this));
|
||||||
this.player.connect('error', this._onPlayerError.bind(this));
|
this.player.connect('error', this._onPlayerError.bind(this));
|
||||||
this.player.connect('state-changed', this._onPlayerStateChanged.bind(this));
|
this.player.connect('state-changed', this._onPlayerStateChanged.bind(this));
|
||||||
|
/*
|
||||||
this.player.connectWidget(
|
this.player.connectWidget(
|
||||||
'button-press-event', this._onPlayerButtonPressEvent.bind(this)
|
'button-press-event', this._onPlayerButtonPressEvent.bind(this)
|
||||||
);
|
);
|
||||||
@@ -176,13 +189,13 @@ var App = GObject.registerClass({
|
|||||||
this.player.connectWidget(
|
this.player.connectWidget(
|
||||||
'motion-notify-event', this._onPlayerMotionNotifyEvent.bind(this)
|
'motion-notify-event', this._onPlayerMotionNotifyEvent.bind(this)
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
/* Widget signals that are disconnected after first run */
|
/* Widget signals that are disconnected after first run */
|
||||||
this._playerRealizeSignal = this.player.widget.connect(
|
this._playerRealizeSignal = this.player.widget.connect(
|
||||||
'realize', this._onPlayerRealize.bind(this)
|
'realize', this._onPlayerRealize.bind(this)
|
||||||
);
|
);
|
||||||
this._playerDrawSignal = this.player.widget.connect(
|
this._playerMapSignal = this.player.widget.connect(
|
||||||
'draw', this._onPlayerDraw.bind(this)
|
'map', this._onPlayerMap.bind(this)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +278,7 @@ var App = GObject.registerClass({
|
|||||||
this.player.renderer.expose();
|
this.player.renderer.expose();
|
||||||
|
|
||||||
let display = this.player.widget.get_display();
|
let display = this.player.widget.get_display();
|
||||||
|
/*
|
||||||
this.defaultCursor = Gdk.Cursor.new_from_name(
|
this.defaultCursor = Gdk.Cursor.new_from_name(
|
||||||
display, 'default'
|
display, 'default'
|
||||||
);
|
);
|
||||||
@@ -274,12 +287,13 @@ var App = GObject.registerClass({
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.playerWindow = this.player.widget.get_window();
|
this.playerWindow = this.player.widget.get_window();
|
||||||
|
*/
|
||||||
this.setHideCursorTimeout();
|
this.setHideCursorTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPlayerDraw(self, data)
|
_onPlayerMap(self, data)
|
||||||
{
|
{
|
||||||
this.player.widget.disconnect(this._playerDrawSignal);
|
this.player.widget.disconnect(this._playerMapSignal);
|
||||||
this.emit('ready', true);
|
this.emit('ready', true);
|
||||||
|
|
||||||
if(this.playlist.length)
|
if(this.playlist.length)
|
||||||
@@ -312,7 +326,7 @@ var App = GObject.registerClass({
|
|||||||
this.inhibitCookie = null;
|
this.inhibitCookie = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('set prevent suspend to: ' + this.is_inhibited(flags));
|
//debug('set prevent suspend to: ' + this.is_inhibited(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPlayerButtonPressEvent(self, event)
|
_onPlayerButtonPressEvent(self, event)
|
||||||
@@ -420,4 +434,11 @@ var App = GObject.registerClass({
|
|||||||
{
|
{
|
||||||
debug(error);
|
debug(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onWindowCloseRequest()
|
||||||
|
{
|
||||||
|
this.window.destroy();
|
||||||
|
this.player.widget.emit('destroy');
|
||||||
|
this.interface.emit('destroy');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
@@ -9,26 +9,26 @@ class BoxedIconButton extends Gtk.Button
|
|||||||
margin_top: 4,
|
margin_top: 4,
|
||||||
margin_bottom: 4,
|
margin_bottom: 4,
|
||||||
can_focus: false,
|
can_focus: false,
|
||||||
can_default: false,
|
//can_default: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.isFullscreen = isFullscreen || false;
|
this.isFullscreen = isFullscreen || false;
|
||||||
|
|
||||||
size = size || Gtk.IconSize.SMALL_TOOLBAR;
|
size = size || Gtk.IconSize.SMALL_TOOLBAR;
|
||||||
let image = Gtk.Image.new_from_icon_name(icon, size);
|
let image = Gtk.Image.new_from_icon_name(icon);
|
||||||
|
|
||||||
if(image)
|
|
||||||
this.set_image(image);
|
|
||||||
|
|
||||||
|
//if(image)
|
||||||
|
//this.set_image(image);
|
||||||
|
/*
|
||||||
this.image.defaultSize = size;
|
this.image.defaultSize = size;
|
||||||
this.image.fullscreenSize = (size === Gtk.IconSize.SMALL_TOOLBAR)
|
this.image.fullscreenSize = (size === Gtk.IconSize.SMALL_TOOLBAR)
|
||||||
? Gtk.IconSize.LARGE_TOOLBAR
|
? Gtk.IconSize.LARGE_TOOLBAR
|
||||||
: Gtk.IconSize.DND;
|
: Gtk.IconSize.DND;
|
||||||
|
*/
|
||||||
this.get_style_context().add_class('flat');
|
this.add_css_class('flat');
|
||||||
|
|
||||||
this.box = new Gtk.Box();
|
this.box = new Gtk.Box();
|
||||||
this.box.pack_start(this, false, false, 0);
|
this.box.append(this);
|
||||||
|
|
||||||
super.show();
|
super.show();
|
||||||
}
|
}
|
||||||
@@ -49,12 +49,12 @@ class BoxedIconButton extends Gtk.Button
|
|||||||
|
|
||||||
this.isFullscreen = isFullscreen;
|
this.isFullscreen = isFullscreen;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
show_all()
|
show_all()
|
||||||
{
|
{
|
||||||
this.box.show_all();
|
this.box.show_all();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
show()
|
show()
|
||||||
{
|
{
|
||||||
this.box.show();
|
this.box.show();
|
||||||
@@ -74,16 +74,16 @@ class BoxedPopoverButton extends BoxedIconButton
|
|||||||
super._init(icon, size, isFullscreen);
|
super._init(icon, size, isFullscreen);
|
||||||
|
|
||||||
this.popover = new Gtk.Popover({
|
this.popover = new Gtk.Popover({
|
||||||
relative_to: this.box
|
default_widget: this.box
|
||||||
});
|
});
|
||||||
this.popoverBox = new Gtk.Box({
|
this.popoverBox = new Gtk.Box({
|
||||||
orientation: Gtk.Orientation.VERTICAL
|
orientation: Gtk.Orientation.VERTICAL
|
||||||
});
|
});
|
||||||
this.popover.add(this.popoverBox);
|
this.popover.set_child(this.popoverBox);
|
||||||
this.popoverBox.show();
|
this.popoverBox.show();
|
||||||
|
|
||||||
if(this.isFullscreen)
|
if(this.isFullscreen)
|
||||||
this.popover.get_style_context().add_class('osd');
|
this.popover.add_css_class('osd');
|
||||||
}
|
}
|
||||||
|
|
||||||
setFullscreenMode(isEnabled)
|
setFullscreenMode(isEnabled)
|
||||||
@@ -91,8 +91,8 @@ class BoxedPopoverButton extends BoxedIconButton
|
|||||||
if(this.isFullscreen === isEnabled)
|
if(this.isFullscreen === isEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let action = (isEnabled) ? 'add_class' : 'remove_class';
|
let action = (isEnabled) ? 'add' : 'remove';
|
||||||
this.popover.get_style_context()[action]('osd');
|
this.popover[action + '_css_class']('osd');
|
||||||
|
|
||||||
super.setFullscreenMode(isEnabled);
|
super.setFullscreenMode(isEnabled);
|
||||||
}
|
}
|
||||||
|
52
clapper_src/controls.js
vendored
52
clapper_src/controls.js
vendored
@@ -57,19 +57,18 @@ var Controls = GObject.registerClass({
|
|||||||
);
|
);
|
||||||
this.fullscreenButton = Gtk.Button.new_from_icon_name(
|
this.fullscreenButton = Gtk.Button.new_from_icon_name(
|
||||||
'view-fullscreen-symbolic',
|
'view-fullscreen-symbolic',
|
||||||
Gtk.IconSize.SMALL_TOOLBAR
|
//Gtk.IconSize.SMALL_TOOLBAR
|
||||||
);
|
);
|
||||||
this.setDefaultWidgetBehaviour(this.fullscreenButton);
|
this.setDefaultWidgetBehaviour(this.fullscreenButton);
|
||||||
this.openMenuButton = Gtk.Button.new_from_icon_name(
|
this.openMenuButton = Gtk.Button.new_from_icon_name(
|
||||||
'open-menu-symbolic',
|
'open-menu-symbolic',
|
||||||
Gtk.IconSize.SMALL_TOOLBAR
|
//Gtk.IconSize.SMALL_TOOLBAR
|
||||||
);
|
);
|
||||||
this.setDefaultWidgetBehaviour(this.openMenuButton);
|
this.setDefaultWidgetBehaviour(this.openMenuButton);
|
||||||
this.forall(this.setDefaultWidgetBehaviour);
|
//this.forall(this.setDefaultWidgetBehaviour);
|
||||||
|
|
||||||
this.realizeSignal = this.connect(
|
this.realizeSignal = this.connect('realize', this._onControlsRealize.bind(this));
|
||||||
'realize', this._onControlsRealize.bind(this)
|
this.destroySignal = this.connect('destroy', this._onControlsDestroy.bind(this));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pack_start(widget, expand, fill, padding)
|
pack_start(widget, expand, fill, padding)
|
||||||
@@ -81,7 +80,7 @@ var Controls = GObject.registerClass({
|
|||||||
)
|
)
|
||||||
widget = widget.box;
|
widget = widget.box;
|
||||||
|
|
||||||
super.pack_start(widget, expand, fill, padding);
|
super.append(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFullscreenMode(isFullscreen)
|
setFullscreenMode(isFullscreen)
|
||||||
@@ -121,6 +120,8 @@ var Controls = GObject.registerClass({
|
|||||||
|
|
||||||
addRadioButtons(box, array, activeId)
|
addRadioButtons(box, array, activeId)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
|
||||||
let group = null;
|
let group = null;
|
||||||
let children = box.get_children();
|
let children = box.get_children();
|
||||||
let lastEl = (children.length > array.length)
|
let lastEl = (children.length > array.length)
|
||||||
@@ -175,7 +176,7 @@ var Controls = GObject.registerClass({
|
|||||||
setDefaultWidgetBehaviour(widget)
|
setDefaultWidgetBehaviour(widget)
|
||||||
{
|
{
|
||||||
widget.can_focus = false;
|
widget.can_focus = false;
|
||||||
widget.can_default = false;
|
//widget.can_default = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setVolumeMarks(isAdded)
|
setVolumeMarks(isAdded)
|
||||||
@@ -212,17 +213,21 @@ var Controls = GObject.registerClass({
|
|||||||
);
|
);
|
||||||
this.togglePlayButton.setPlayImage = () =>
|
this.togglePlayButton.setPlayImage = () =>
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
this.togglePlayButton.image.set_from_icon_name(
|
this.togglePlayButton.image.set_from_icon_name(
|
||||||
'media-playback-start-symbolic',
|
'media-playback-start-symbolic',
|
||||||
this.togglePlayButton.image.icon_size
|
this.togglePlayButton.image.icon_size
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
this.togglePlayButton.setPauseImage = () =>
|
this.togglePlayButton.setPauseImage = () =>
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
this.togglePlayButton.image.set_from_icon_name(
|
this.togglePlayButton.image.set_from_icon_name(
|
||||||
'media-playback-pause-symbolic',
|
'media-playback-pause-symbolic',
|
||||||
this.togglePlayButton.image.icon_size
|
this.togglePlayButton.image.icon_size
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,19 +239,18 @@ var Controls = GObject.registerClass({
|
|||||||
draw_value: true,
|
draw_value: true,
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
});
|
});
|
||||||
let style = this.positionScale.get_style_context();
|
this.positionScale.add_css_class('positionscale');
|
||||||
style.add_class('positionscale');
|
this.positionScale.set_format_value_func(
|
||||||
|
this._onPositionScaleFormatValue.bind(this)
|
||||||
this.positionScale.connect(
|
|
||||||
'format-value', this._onPositionScaleFormatValue.bind(this)
|
|
||||||
);
|
);
|
||||||
|
/*
|
||||||
this.positionScale.connect(
|
this.positionScale.connect(
|
||||||
'button-press-event', this._onPositionScaleButtonPressEvent.bind(this)
|
'button-press-event', this._onPositionScaleButtonPressEvent.bind(this)
|
||||||
);
|
);
|
||||||
this.positionScale.connect(
|
this.positionScale.connect(
|
||||||
'button-release-event', this._onPositionScaleButtonReleaseEvent.bind(this)
|
'button-release-event', this._onPositionScaleButtonReleaseEvent.bind(this)
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
this.positionAdjustment = this.positionScale.get_adjustment();
|
this.positionAdjustment = this.positionScale.get_adjustment();
|
||||||
this.pack_start(this.positionScale, true, true, 0);
|
this.pack_start(this.positionScale, true, true, 0);
|
||||||
}
|
}
|
||||||
@@ -256,10 +260,10 @@ var Controls = GObject.registerClass({
|
|||||||
this.volumeButton = this.addPopoverButton(
|
this.volumeButton = this.addPopoverButton(
|
||||||
'audio-volume-muted-symbolic'
|
'audio-volume-muted-symbolic'
|
||||||
);
|
);
|
||||||
this.volumeButton.add_events(Gdk.EventMask.SCROLL_MASK);
|
//this.volumeButton.add_events(Gdk.EventMask.SCROLL_MASK);
|
||||||
this.volumeButton.connect(
|
//this.volumeButton.connect(
|
||||||
'scroll-event', (self, event) => this._onScrollEvent(event)
|
// 'scroll-event', (self, event) => this._onScrollEvent(event)
|
||||||
);
|
//);
|
||||||
this.volumeScale = new Gtk.Scale({
|
this.volumeScale = new Gtk.Scale({
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
inverted: true,
|
inverted: true,
|
||||||
@@ -268,7 +272,7 @@ var Controls = GObject.registerClass({
|
|||||||
round_digits: 2,
|
round_digits: 2,
|
||||||
vexpand: true,
|
vexpand: true,
|
||||||
});
|
});
|
||||||
this.volumeScale.get_style_context().add_class('volumescale');
|
this.volumeScale.add_css_class('volumescale');
|
||||||
this.volumeAdjustment = this.volumeScale.get_adjustment();
|
this.volumeAdjustment = this.volumeScale.get_adjustment();
|
||||||
|
|
||||||
this.volumeAdjustment.set_upper(2);
|
this.volumeAdjustment.set_upper(2);
|
||||||
@@ -276,8 +280,8 @@ var Controls = GObject.registerClass({
|
|||||||
this.volumeAdjustment.set_page_increment(0.05);
|
this.volumeAdjustment.set_page_increment(0.05);
|
||||||
this.setDefaultWidgetBehaviour(this.volumeScale);
|
this.setDefaultWidgetBehaviour(this.volumeScale);
|
||||||
|
|
||||||
this.volumeButton.popoverBox.add(this.volumeScale);
|
this.volumeButton.popoverBox.append(this.volumeScale);
|
||||||
this.volumeButton.popoverBox.show_all();
|
//this.volumeButton.popoverBox.show_all();
|
||||||
|
|
||||||
this.setVolumeMarks(true);
|
this.setVolumeMarks(true);
|
||||||
}
|
}
|
||||||
@@ -375,4 +379,10 @@ var Controls = GObject.registerClass({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onControlsDestroy()
|
||||||
|
{
|
||||||
|
this.disconnect(this.destroySignal);
|
||||||
|
this.positionScale.set_format_value_func(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
73
clapper_src/headerbar.js
Normal file
73
clapper_src/headerbar.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
const { GLib, GObject, Gtk, Pango } = imports.gi;
|
||||||
|
|
||||||
|
var HeaderBar = GObject.registerClass(
|
||||||
|
class ClapperHeaderBar extends Gtk.HeaderBar
|
||||||
|
{
|
||||||
|
_init(window, startButtons, endButtons)
|
||||||
|
{
|
||||||
|
super._init();
|
||||||
|
|
||||||
|
this.set_title_widget(this._createWidgetForWindow(window));
|
||||||
|
startButtons.forEach(btn => this.pack_start(btn));
|
||||||
|
endButtons.forEach(btn => this.pack_end(btn));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHeaderBar(mediaInfo)
|
||||||
|
{
|
||||||
|
let title = mediaInfo.get_title();
|
||||||
|
let subtitle = mediaInfo.get_uri() || null;
|
||||||
|
|
||||||
|
if(subtitle && subtitle.startsWith('file://')) {
|
||||||
|
subtitle = GLib.filename_from_uri(subtitle)[0];
|
||||||
|
subtitle = GLib.path_get_basename(subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!title) {
|
||||||
|
title = (!subtitle)
|
||||||
|
? this.defaultTitle
|
||||||
|
: (subtitle.includes('.'))
|
||||||
|
? subtitle.split('.').slice(0, -1).join('.')
|
||||||
|
: subtitle;
|
||||||
|
|
||||||
|
subtitle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.titleLabel.label = title;
|
||||||
|
this.subtitleLabel.visible = (subtitle !== null);
|
||||||
|
|
||||||
|
if(subtitle)
|
||||||
|
this.subtitleLabel.label = subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
_createWidgetForWindow(window)
|
||||||
|
{
|
||||||
|
let box = new Gtk.Box ({
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
valign: Gtk.Align.CENTER
|
||||||
|
});
|
||||||
|
|
||||||
|
this.titleLabel = new Gtk.Label({
|
||||||
|
halign: Gtk.Align.CENTER,
|
||||||
|
single_line_mode: true,
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
width_chars: 5,
|
||||||
|
});
|
||||||
|
this.titleLabel.add_css_class('title');
|
||||||
|
this.titleLabel.set_parent(box);
|
||||||
|
|
||||||
|
window.bind_property('title', this.titleLabel, 'label',
|
||||||
|
GObject.BindingFlags.SYNC_CREATE
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subtitleLabel = new Gtk.Label({
|
||||||
|
halign: Gtk.Align.CENTER,
|
||||||
|
single_line_mode: true,
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
});
|
||||||
|
this.subtitleLabel.add_css_class('subtitle');
|
||||||
|
this.subtitleLabel.set_parent(box);
|
||||||
|
this.subtitleLabel.visible = false;
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
});
|
@@ -33,29 +33,33 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
this.revealerBottom = new Revealers.RevealerBottom();
|
this.revealerBottom = new Revealers.RevealerBottom();
|
||||||
this.controls = new Controls();
|
this.controls = new Controls();
|
||||||
|
|
||||||
this.videoBox.get_style_context().add_class('videobox');
|
this.videoBox.add_css_class('videobox');
|
||||||
this.videoBox.pack_start(this.overlay, true, true, 0);
|
this.videoBox.append(this.overlay);
|
||||||
this.attach(this.videoBox, 0, 0, 1, 1);
|
this.attach(this.videoBox, 0, 0, 1, 1);
|
||||||
this.attach(this.controls, 0, 1, 1, 1);
|
this.attach(this.controls, 0, 1, 1, 1);
|
||||||
|
|
||||||
|
this.destroySignal = this.connect('destroy', this._onInterfaceDestroy.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
addPlayer(player)
|
addPlayer(player)
|
||||||
{
|
{
|
||||||
this._player = player;
|
this._player = player;
|
||||||
this._player.widget.expand = true;
|
this._player.widget.vexpand = true;
|
||||||
|
this._player.widget.hexpand = true;
|
||||||
|
|
||||||
this._player.connect('state-changed', this._onPlayerStateChanged.bind(this));
|
this._player.connect('state-changed', this._onPlayerStateChanged.bind(this));
|
||||||
this._player.connect('volume-changed', this._onPlayerVolumeChanged.bind(this));
|
this._player.connect('volume-changed', this._onPlayerVolumeChanged.bind(this));
|
||||||
this._player.connect('duration-changed', this._onPlayerDurationChanged.bind(this));
|
this._player.connect('duration-changed', this._onPlayerDurationChanged.bind(this));
|
||||||
this._player.connect('position-updated', this._onPlayerPositionUpdated.bind(this));
|
this._player.connect('position-updated', this._onPlayerPositionUpdated.bind(this));
|
||||||
|
/*
|
||||||
this._player.connectWidget(
|
this._player.connectWidget(
|
||||||
'scroll-event', (self, event) => this.controls._onScrollEvent(event)
|
'scroll-event', (self, event) => this.controls._onScrollEvent(event)
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
this.controls.togglePlayButton.connect(
|
this.controls.togglePlayButton.connect(
|
||||||
'clicked', this._onControlsTogglePlayClicked.bind(this)
|
'clicked', this._onControlsTogglePlayClicked.bind(this)
|
||||||
);
|
);
|
||||||
this.controls.positionScale.connect(
|
this.scaleSig = this.controls.positionScale.connect(
|
||||||
'value-changed', this._onControlsPositionChanged.bind(this)
|
'value-changed', this._onControlsPositionChanged.bind(this)
|
||||||
);
|
);
|
||||||
this.controls.volumeScale.connect(
|
this.controls.volumeScale.connect(
|
||||||
@@ -70,9 +74,9 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
this.controls.connect(
|
this.controls.connect(
|
||||||
'visualization-change-requested', this._onVisualizationChangeRequested.bind(this)
|
'visualization-change-requested', this._onVisualizationChangeRequested.bind(this)
|
||||||
);
|
);
|
||||||
this.revealerTop.connect('event-after', (self, event) => this._player.widget.event(event));
|
//this.revealerTop.connect('event-after', (self, event) => this._player.widget.event(event));
|
||||||
|
|
||||||
this.overlay.add(this._player.widget);
|
this.overlay.set_child(this._player.widget);
|
||||||
this.overlay.add_overlay(this.revealerTop);
|
this.overlay.add_overlay(this.revealerTop);
|
||||||
this.overlay.add_overlay(this.revealerBottom);
|
this.overlay.add_overlay(this.revealerBottom);
|
||||||
|
|
||||||
@@ -122,8 +126,8 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
{
|
{
|
||||||
let mediaInfo = this._player.get_media_info();
|
let mediaInfo = this._player.get_media_info();
|
||||||
|
|
||||||
// set titlebar media title and path
|
/* Set titlebar media title and path */
|
||||||
this.updateHeaderBar(mediaInfo);
|
this.updateTitles(mediaInfo);
|
||||||
|
|
||||||
// we can also check if video is "live" or "seekable" (right now unused)
|
// we can also check if video is "live" or "seekable" (right now unused)
|
||||||
// it might be a good idea to hide position seek bar and disable seeking
|
// it might be a good idea to hide position seek bar and disable seeking
|
||||||
@@ -220,32 +224,12 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHeaderBar(mediaInfo)
|
updateTitles(mediaInfo)
|
||||||
{
|
{
|
||||||
if(!this.headerBar)
|
if(this.headerBar)
|
||||||
return;
|
this.headerBar.updateHeaderBar(mediaInfo);
|
||||||
|
|
||||||
let title = mediaInfo.get_title();
|
this.revealerTop.setMediaTitle(this.headerBar.titleLabel.label);
|
||||||
let subtitle = mediaInfo.get_uri() || null;
|
|
||||||
|
|
||||||
if(subtitle.startsWith('file://')) {
|
|
||||||
subtitle = GLib.filename_from_uri(subtitle)[0];
|
|
||||||
subtitle = GLib.path_get_basename(subtitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!title) {
|
|
||||||
title = (!subtitle)
|
|
||||||
? this.defaultTitle
|
|
||||||
: (subtitle.includes('.'))
|
|
||||||
? subtitle.split('.').slice(0, -1).join('.')
|
|
||||||
: subtitle;
|
|
||||||
|
|
||||||
subtitle = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.headerBar.set_title(title);
|
|
||||||
this.headerBar.set_subtitle(subtitle);
|
|
||||||
this.revealerTop.setMediaTitle(title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTime()
|
updateTime()
|
||||||
@@ -300,8 +284,8 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
|
|
||||||
_onTrackChangeRequested(self, type, activeId)
|
_onTrackChangeRequested(self, type, activeId)
|
||||||
{
|
{
|
||||||
// reenabling audio is slow (as expected),
|
/* Reenabling audio is slow (as expected),
|
||||||
// so it is better to toggle mute instead
|
* so it is better to toggle mute instead */
|
||||||
if(type === 'audio') {
|
if(type === 'audio') {
|
||||||
if(activeId < 0)
|
if(activeId < 0)
|
||||||
return this._player.set_mute(true);
|
return this._player.set_mute(true);
|
||||||
@@ -313,8 +297,8 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(activeId < 0) {
|
if(activeId < 0) {
|
||||||
// disabling video leaves last frame frozen,
|
/* Disabling video leaves last frame frozen,
|
||||||
// so we hide it by making it transparent
|
* so we hide it by making it transparent */
|
||||||
if(type === 'video')
|
if(type === 'video')
|
||||||
this._player.widget.set_opacity(0);
|
this._player.widget.set_opacity(0);
|
||||||
|
|
||||||
@@ -468,7 +452,7 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
: 'overamplified';
|
: 'overamplified';
|
||||||
|
|
||||||
let iconName = `audio-volume-${icon}-symbolic`;
|
let iconName = `audio-volume-${icon}-symbolic`;
|
||||||
|
/*
|
||||||
if(this.controls.volumeButton.image.icon_name !== iconName)
|
if(this.controls.volumeButton.image.icon_name !== iconName)
|
||||||
{
|
{
|
||||||
debug(`set volume icon: ${icon}`);
|
debug(`set volume icon: ${icon}`);
|
||||||
@@ -477,11 +461,17 @@ class ClapperInterface extends Gtk.Grid
|
|||||||
this.controls.volumeButton.image.icon_size
|
this.controls.volumeButton.image.icon_size
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if(volume === this.lastVolumeValue)
|
if(volume === this.lastVolumeValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.lastVolumeValue = volume;
|
this.lastVolumeValue = volume;
|
||||||
this._player.set_volume(volume);
|
this._player.set_volume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onInterfaceDestroy()
|
||||||
|
{
|
||||||
|
this.disconnect(this.destroySignal);
|
||||||
|
this.controls.emit('destroy');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
@@ -21,7 +21,16 @@ class ClapperPlayer extends GstPlayer.Player
|
|||||||
if(!Gst.is_initialized())
|
if(!Gst.is_initialized())
|
||||||
Gst.init(null);
|
Gst.init(null);
|
||||||
|
|
||||||
let gtkglsink = Gst.ElementFactory.make('gtkglsink', null);
|
let plugin = 'gtk4glsink';
|
||||||
|
let gtkglsink = Gst.ElementFactory.make(plugin, null);
|
||||||
|
|
||||||
|
if(!gtkglsink) {
|
||||||
|
return debug(new Error(
|
||||||
|
`Could not load "${plugin}".`
|
||||||
|
+ ' Do you have gstreamer-plugins-good-gtk4 installed?'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let glsinkbin = Gst.ElementFactory.make('glsinkbin', null);
|
let glsinkbin = Gst.ElementFactory.make('glsinkbin', null);
|
||||||
glsinkbin.sink = gtkglsink;
|
glsinkbin.sink = gtkglsink;
|
||||||
|
|
||||||
@@ -35,8 +44,7 @@ class ClapperPlayer extends GstPlayer.Player
|
|||||||
video_renderer: renderer
|
video_renderer: renderer
|
||||||
});
|
});
|
||||||
|
|
||||||
// assign elements to player for later access
|
/* Assign elements to player for later access */
|
||||||
// and make sure that GJS will not free them early
|
|
||||||
this.gtkglsink = gtkglsink;
|
this.gtkglsink = gtkglsink;
|
||||||
this.glsinkbin = glsinkbin;
|
this.glsinkbin = glsinkbin;
|
||||||
this.dispatcher = dispatcher;
|
this.dispatcher = dispatcher;
|
||||||
@@ -61,6 +69,10 @@ class ClapperPlayer extends GstPlayer.Player
|
|||||||
this.set_config(config);
|
this.set_config(config);
|
||||||
this.set_mute(false);
|
this.set_mute(false);
|
||||||
|
|
||||||
|
/* FIXME: remove once GUI buttons are back */
|
||||||
|
this.set_volume(0.5);
|
||||||
|
this.set_plugin_rank('vah264dec', 300);
|
||||||
|
|
||||||
this.loop = GLib.MainLoop.new(null, false);
|
this.loop = GLib.MainLoop.new(null, false);
|
||||||
this.run_loop = opts.run_loop || false;
|
this.run_loop = opts.run_loop || false;
|
||||||
this.widget = gtkglsink.widget;
|
this.widget = gtkglsink.widget;
|
||||||
|
@@ -130,7 +130,7 @@ class ClapperRevealerTop extends CustomRevealer
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.revealerName = 'top';
|
this.revealerName = 'top';
|
||||||
|
/*
|
||||||
this.set_events(
|
this.set_events(
|
||||||
Gdk.EventMask.BUTTON_PRESS_MASK
|
Gdk.EventMask.BUTTON_PRESS_MASK
|
||||||
| Gdk.EventMask.BUTTON_RELEASE_MASK
|
| Gdk.EventMask.BUTTON_RELEASE_MASK
|
||||||
@@ -141,7 +141,7 @@ class ClapperRevealerTop extends CustomRevealer
|
|||||||
| Gdk.EventMask.ENTER_NOTIFY_MASK
|
| Gdk.EventMask.ENTER_NOTIFY_MASK
|
||||||
| Gdk.EventMask.LEAVE_NOTIFY_MASK
|
| Gdk.EventMask.LEAVE_NOTIFY_MASK
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
let initTime = GLib.DateTime.new_now_local().format('%X');
|
let initTime = GLib.DateTime.new_now_local().format('%X');
|
||||||
this.timeFormat = (initTime.length > 8)
|
this.timeFormat = (initTime.length > 8)
|
||||||
? '%I:%M %p'
|
? '%I:%M %p'
|
||||||
@@ -150,13 +150,13 @@ class ClapperRevealerTop extends CustomRevealer
|
|||||||
this.revealerGrid = new Gtk.Grid({
|
this.revealerGrid = new Gtk.Grid({
|
||||||
column_spacing: 8
|
column_spacing: 8
|
||||||
});
|
});
|
||||||
let gridContext = this.revealerGrid.get_style_context();
|
this.revealerGrid.add_css_class('osd');
|
||||||
gridContext.add_class('osd');
|
this.revealerGrid.add_css_class('reavealertop');
|
||||||
gridContext.add_class('reavealertop');
|
|
||||||
|
|
||||||
this.mediaTitle = new Gtk.Label({
|
this.mediaTitle = new Gtk.Label({
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
expand: true,
|
vexpand: true,
|
||||||
|
hexpand: true,
|
||||||
margin_top: 14,
|
margin_top: 14,
|
||||||
margin_start: 12,
|
margin_start: 12,
|
||||||
xalign: 0,
|
xalign: 0,
|
||||||
@@ -169,17 +169,17 @@ class ClapperRevealerTop extends CustomRevealer
|
|||||||
yalign: 0,
|
yalign: 0,
|
||||||
};
|
};
|
||||||
this.currentTime = new Gtk.Label(timeLabelOpts);
|
this.currentTime = new Gtk.Label(timeLabelOpts);
|
||||||
this.currentTime.get_style_context().add_class('osdtime');
|
this.currentTime.add_css_class('osdtime');
|
||||||
|
|
||||||
this.endTime = new Gtk.Label(timeLabelOpts);
|
this.endTime = new Gtk.Label(timeLabelOpts);
|
||||||
this.endTime.get_style_context().add_class('osdendtime');
|
this.endTime.add_css_class('osdendtime');
|
||||||
|
|
||||||
this.revealerGrid.attach(this.mediaTitle, 0, 0, 1, 1);
|
this.revealerGrid.attach(this.mediaTitle, 0, 0, 1, 1);
|
||||||
this.revealerGrid.attach(this.currentTime, 1, 0, 1, 1);
|
this.revealerGrid.attach(this.currentTime, 1, 0, 1, 1);
|
||||||
this.revealerGrid.attach(this.endTime, 1, 0, 1, 1);
|
this.revealerGrid.attach(this.endTime, 1, 0, 1, 1);
|
||||||
|
|
||||||
this.add(this.revealerGrid);
|
this.set_child(this.revealerGrid);
|
||||||
this.revealerGrid.show_all();
|
//this.revealerGrid.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
setMediaTitle(title)
|
setMediaTitle(title)
|
||||||
@@ -217,10 +217,10 @@ class ClapperRevealerBottom extends CustomRevealer
|
|||||||
|
|
||||||
this.revealerName = 'bottom';
|
this.revealerName = 'bottom';
|
||||||
this.revealerBox = new Gtk.Box();
|
this.revealerBox = new Gtk.Box();
|
||||||
this.revealerBox.get_style_context().add_class('osd');
|
this.revealerBox.add_css_class('osd');
|
||||||
|
|
||||||
this.add(this.revealerBox);
|
this.set_child(this.revealerBox);
|
||||||
this.revealerBox.show_all();
|
//this.revealerBox.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
addWidget(widget)
|
addWidget(widget)
|
||||||
|
@@ -13,11 +13,12 @@ var Window = GObject.registerClass({
|
|||||||
super._init({
|
super._init({
|
||||||
application: application,
|
application: application,
|
||||||
title: title || 'Clapper',
|
title: title || 'Clapper',
|
||||||
border_width: 0,
|
//border_width: 0,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
window_position: Gtk.WindowPosition.CENTER,
|
//window_position: Gtk.WindowPosition.CENTER,
|
||||||
width_request: 960,
|
width_request: 960,
|
||||||
height_request: 642
|
height_request: 642,
|
||||||
|
destroy_with_parent: true,
|
||||||
});
|
});
|
||||||
this.isFullscreen = false;
|
this.isFullscreen = false;
|
||||||
}
|
}
|
||||||
@@ -27,7 +28,7 @@ var Window = GObject.registerClass({
|
|||||||
let un = (this.isFullscreen) ? 'un' : '';
|
let un = (this.isFullscreen) ? 'un' : '';
|
||||||
this[`${un}fullscreen`]();
|
this[`${un}fullscreen`]();
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
vfunc_window_state_event(event)
|
vfunc_window_state_event(event)
|
||||||
{
|
{
|
||||||
super.vfunc_window_state_event(event);
|
super.vfunc_window_state_event(event);
|
||||||
@@ -43,4 +44,5 @@ var Window = GObject.registerClass({
|
|||||||
this.isFullscreen = isFullscreen;
|
this.isFullscreen = isFullscreen;
|
||||||
this.emit('fullscreen-changed', this.isFullscreen);
|
this.emit('fullscreen-changed', this.isFullscreen);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
imports.gi.versions.Gdk = '3.0';
|
imports.gi.versions.Gdk = '4.0';
|
||||||
imports.gi.versions.Gtk = '3.0';
|
imports.gi.versions.Gtk = '4.0';
|
||||||
imports.searchPath.unshift('@importspath@');
|
imports.searchPath.unshift('@importspath@');
|
||||||
|
|
||||||
const ClapperSrc = imports.clapper_src;
|
const ClapperSrc = imports.clapper_src;
|
||||||
|
4
main.js
4
main.js
@@ -1,5 +1,5 @@
|
|||||||
imports.gi.versions.Gdk = '3.0';
|
imports.gi.versions.Gdk = '4.0';
|
||||||
imports.gi.versions.Gtk = '3.0';
|
imports.gi.versions.Gtk = '4.0';
|
||||||
|
|
||||||
const { Gst } = imports.gi;
|
const { Gst } = imports.gi;
|
||||||
const { App } = imports.clapper_src.app;
|
const { App } = imports.clapper_src.app;
|
||||||
|
Reference in New Issue
Block a user