mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 07:42:23 +02:00
When a media is changed, normally one would expect to create new radio buttons with video/audio/subtitle tracks names corresponding to current video, but this is inefficient. Destroying objects just to create similiar ones again does take a long time and might lead to memory leaks. That is why a better and faster approach is to simply edit already available objects to match our expectations instead. This commit does just that for tracks radio buttons.
320 lines
9.4 KiB
JavaScript
320 lines
9.4 KiB
JavaScript
const { GObject, Gtk } = imports.gi;
|
|
const Debug = imports.clapper_src.debug;
|
|
|
|
const CONTROLS_MARGIN = 4;
|
|
const CONTROLS_SPACING = 4;
|
|
|
|
let { debug } = Debug;
|
|
|
|
var Controls = GObject.registerClass({
|
|
Signals: {
|
|
'position-seeking-changed': {
|
|
param_types: [GObject.TYPE_BOOLEAN]
|
|
},
|
|
'track-change-requested': {
|
|
param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
|
|
},
|
|
}
|
|
}, class ClapperControls extends Gtk.HBox
|
|
{
|
|
_init()
|
|
{
|
|
super._init({
|
|
margin_left: CONTROLS_MARGIN,
|
|
margin_right: CONTROLS_MARGIN,
|
|
spacing: CONTROLS_SPACING,
|
|
valign: Gtk.Align.END,
|
|
});
|
|
|
|
this._fullscreenMode = false;
|
|
this.durationFormated = '00:00:00';
|
|
this.buttonImages = [];
|
|
|
|
this._addTogglePlayButton();
|
|
this._addPositionScale();
|
|
this.videoTracksButton = this.addPopoverButton(
|
|
'emblem-videos-symbolic'
|
|
);
|
|
this.audioTracksButton = this.addPopoverButton(
|
|
'emblem-music-symbolic'
|
|
);
|
|
this.subtitleTracksButton = this.addPopoverButton(
|
|
'media-view-subtitles-symbolic'
|
|
);
|
|
this._addVolumeButton();
|
|
this.unfullscreenButton = this.addButton(
|
|
'view-restore-symbolic',
|
|
Gtk.IconSize.SMALL_TOOLBAR,
|
|
true
|
|
);
|
|
|
|
this.fullscreenButton = Gtk.Button.new_from_icon_name(
|
|
'view-fullscreen-symbolic',
|
|
Gtk.IconSize.SMALL_TOOLBAR
|
|
);
|
|
this.setDefaultWidgetBehaviour(this.fullscreenButton);
|
|
this.openMenuButton = Gtk.Button.new_from_icon_name(
|
|
'open-menu-symbolic',
|
|
Gtk.IconSize.SMALL_TOOLBAR
|
|
);
|
|
this.setDefaultWidgetBehaviour(this.openMenuButton);
|
|
|
|
this.forall(this.setDefaultWidgetBehaviour);
|
|
}
|
|
|
|
set fullscreenMode(isFullscreen)
|
|
{
|
|
if(isFullscreen === this._fullscreenMode)
|
|
return;
|
|
|
|
for(let image of this.buttonImages) {
|
|
image.icon_size = (isFullscreen)
|
|
? image.fullscreenSize
|
|
: image.defaultSize;
|
|
}
|
|
|
|
this._fullscreenMode = isFullscreen;
|
|
}
|
|
|
|
get fullscreenMode()
|
|
{
|
|
return this._fullscreenMode;
|
|
}
|
|
|
|
addButton(iconName, size, noPack)
|
|
{
|
|
size = size || Gtk.IconSize.SMALL_TOOLBAR;
|
|
|
|
let button = Gtk.Button.new_from_icon_name(iconName, size);
|
|
let box = new Gtk.Box();
|
|
|
|
button.margin_top = CONTROLS_MARGIN;
|
|
button.margin_bottom = CONTROLS_MARGIN;
|
|
button.image.defaultSize = size;
|
|
button.image.fullscreenSize = (size === Gtk.IconSize.SMALL_TOOLBAR)
|
|
? Gtk.IconSize.LARGE_TOOLBAR
|
|
: Gtk.IconSize.DND;
|
|
|
|
this.setDefaultWidgetBehaviour(button);
|
|
button.get_style_context().add_class('flat');
|
|
|
|
if(!noPack) {
|
|
box.pack_start(button, false, false, 0);
|
|
this.pack_start(box, false, false, 0);
|
|
box.show_all();
|
|
}
|
|
|
|
this.buttonImages.push(button.image);
|
|
return button;
|
|
}
|
|
|
|
addPopoverButton(iconName, size)
|
|
{
|
|
let button = this.addButton(iconName, size);
|
|
|
|
button.popover = new Gtk.Popover({
|
|
relative_to: button.get_parent()
|
|
});
|
|
button.popoverBox = new Gtk.VBox();
|
|
button.osd = this.fullscreenMode;
|
|
button.popover.add(button.popoverBox);
|
|
button.connect('clicked', this._onPopoverButtonClicked.bind(this, button));
|
|
button.popoverBox.show();
|
|
|
|
return button;
|
|
}
|
|
|
|
addRadioButtons(box, array, activeId)
|
|
{
|
|
let group = null;
|
|
let children = box.get_children();
|
|
let lastEl = (children.length > array.length)
|
|
? children.length
|
|
: array.length;
|
|
|
|
for(let i = 0; i < lastEl; i++) {
|
|
if(i >= array.length) {
|
|
children[i].hide();
|
|
debug(`hiding unused ${children[i].trackType} radioButton nr: ${i}`);
|
|
continue;
|
|
}
|
|
|
|
let el = array[i];
|
|
let radioButton;
|
|
|
|
if(i < children.length) {
|
|
radioButton = children[i];
|
|
debug(`reusing ${el.type} radioButton nr: ${i}`);
|
|
}
|
|
else {
|
|
debug(`creating new ${el.type} radioButton nr: ${i}`);
|
|
radioButton = new Gtk.RadioButton({
|
|
group: group,
|
|
});
|
|
radioButton.connect(
|
|
'toggled',
|
|
this._onTrackRadioButtonToggled.bind(this, radioButton)
|
|
);
|
|
this.setDefaultWidgetBehaviour(radioButton);
|
|
box.add(radioButton);
|
|
}
|
|
radioButton.label = el.label;
|
|
debug(`radioButton label: ${radioButton.label}`);
|
|
radioButton.trackType = el.type;
|
|
debug(`radioButton type: ${radioButton.trackType}`);
|
|
radioButton.trackId = el.value;
|
|
debug(`radioButton track id: ${radioButton.trackId}`);
|
|
|
|
if(radioButton.trackId === activeId) {
|
|
radioButton.set_active(true);
|
|
debug(`activated ${el.type} radioButton nr: ${i}`);
|
|
}
|
|
if(!group)
|
|
group = radioButton;
|
|
|
|
radioButton.show();
|
|
}
|
|
}
|
|
|
|
setDefaultWidgetBehaviour(widget)
|
|
{
|
|
widget.can_focus = false;
|
|
widget.can_default = false;
|
|
}
|
|
|
|
setVolumeMarks(isAdded)
|
|
{
|
|
if(!isAdded)
|
|
return this.volumeScale.clear_marks();
|
|
|
|
this.volumeScale.add_mark(0, Gtk.PositionType.LEFT, '0%');
|
|
this.volumeScale.add_mark(1, Gtk.PositionType.LEFT, '100%');
|
|
this.volumeScale.add_mark(2, Gtk.PositionType.LEFT, '200%');
|
|
}
|
|
|
|
_addTogglePlayButton()
|
|
{
|
|
this.togglePlayButton = this.addButton(
|
|
'media-playback-pause-symbolic',
|
|
Gtk.IconSize.LARGE_TOOLBAR
|
|
);
|
|
this.togglePlayButton.setPlayImage = () =>
|
|
{
|
|
this.togglePlayButton.image.set_from_icon_name(
|
|
'media-playback-start-symbolic',
|
|
this.togglePlayButton.image.icon_size
|
|
);
|
|
}
|
|
this.togglePlayButton.setPauseImage = () =>
|
|
{
|
|
this.togglePlayButton.image.set_from_icon_name(
|
|
'media-playback-pause-symbolic',
|
|
this.togglePlayButton.image.icon_size
|
|
);
|
|
}
|
|
}
|
|
|
|
_addPositionScale()
|
|
{
|
|
this.positionScale = new Gtk.Scale({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
value_pos: Gtk.PositionType.LEFT,
|
|
draw_value: true,
|
|
hexpand: true,
|
|
});
|
|
let style = this.positionScale.get_style_context();
|
|
style.add_class('positionscale');
|
|
|
|
this.positionScale.connect(
|
|
'format-value', this._onPositionScaleFormatValue.bind(this)
|
|
);
|
|
this.positionScale.connect(
|
|
'button-press-event', this._onPositionScaleButtonPressEvent.bind(this)
|
|
);
|
|
this.positionScale.connect(
|
|
'button-release-event', this._onPositionScaleButtonReleaseEvent.bind(this)
|
|
);
|
|
|
|
this.positionAdjustment = this.positionScale.get_adjustment();
|
|
this.pack_start(this.positionScale, true, true, 0);
|
|
}
|
|
|
|
_addVolumeButton()
|
|
{
|
|
this.volumeButton = this.addPopoverButton(
|
|
'audio-volume-muted-symbolic'
|
|
);
|
|
this.volumeScale = new Gtk.Scale({
|
|
orientation: Gtk.Orientation.VERTICAL,
|
|
inverted: true,
|
|
value_pos: Gtk.PositionType.TOP,
|
|
draw_value: false,
|
|
round_digits: 2,
|
|
vexpand: true,
|
|
});
|
|
this.volumeScale.get_style_context().add_class('volumescale');
|
|
this.volumeAdjustment = this.volumeScale.get_adjustment();
|
|
|
|
this.volumeAdjustment.set_upper(2);
|
|
this.volumeAdjustment.set_step_increment(0.05);
|
|
this.volumeAdjustment.set_page_increment(0.05);
|
|
this.setDefaultWidgetBehaviour(this.volumeScale);
|
|
|
|
this.volumeButton.popoverBox.add(this.volumeScale);
|
|
this.volumeButton.popoverBox.show_all();
|
|
|
|
this.setVolumeMarks(true);
|
|
}
|
|
|
|
_getFormatedTime(time)
|
|
{
|
|
let hours = ('0' + Math.floor(time / 3600)).slice(-2);
|
|
time -= hours * 3600;
|
|
let minutes = ('0' + Math.floor(time / 60)).slice(-2);
|
|
time -= minutes * 60;
|
|
let seconds = ('0' + Math.floor(time)).slice(-2);
|
|
|
|
return `${hours}:${minutes}:${seconds}`;
|
|
}
|
|
|
|
_onPopoverButtonClicked(self, button)
|
|
{
|
|
if(button.osd !== this.fullscreenMode) {
|
|
let action = (this.fullscreenMode) ? 'add_class' : 'remove_class';
|
|
button.popover.get_style_context()[action]('osd');
|
|
button.osd = this.fullscreenMode;
|
|
}
|
|
button.popover.popup();
|
|
}
|
|
|
|
_onTrackRadioButtonToggled(self, radioButton)
|
|
{
|
|
if(!radioButton.get_active())
|
|
return;
|
|
|
|
this.emit(
|
|
'track-change-requested',
|
|
radioButton.trackType,
|
|
radioButton.trackId
|
|
);
|
|
}
|
|
|
|
_onPositionScaleFormatValue(self, value)
|
|
{
|
|
return this._getFormatedTime(value)
|
|
+ '/' + this.durationFormated;
|
|
}
|
|
|
|
_onPositionScaleButtonPressEvent()
|
|
{
|
|
this.isPositionSeeking = true;
|
|
this.emit('position-seeking-changed', this.isPositionSeeking);
|
|
}
|
|
|
|
_onPositionScaleButtonReleaseEvent()
|
|
{
|
|
this.isPositionSeeking = false;
|
|
this.emit('position-seeking-changed', this.isPositionSeeking);
|
|
}
|
|
});
|