mirror of
				https://github.com/Rafostar/clapper.git
				synced 2025-10-31 10:25:45 +01:00 
			
		
		
		
	Add Gtk app
This commit is contained in:
		
							
								
								
									
										62
									
								
								clapper_src/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								clapper_src/app.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| const { GLib, GObject, Gtk } = imports.gi; | ||||
| const { Player } = imports.clapper_src.player; | ||||
| const { Interface } = imports.clapper_src.interface; | ||||
|  | ||||
| const APP_NAME = 'Clapper'; | ||||
|  | ||||
| var App = GObject.registerClass({ | ||||
|     Signals: { | ||||
|         'player-ready': { | ||||
|             param_types: [GObject.TYPE_BOOLEAN] | ||||
|         } | ||||
|     } | ||||
| }, class ClapperApp extends Gtk.Application | ||||
| { | ||||
|     _init(args) | ||||
|     { | ||||
|         GLib.set_prgname(APP_NAME); | ||||
|  | ||||
|         super._init(); | ||||
|  | ||||
|         this.connect('startup', () => this._buildUI()); | ||||
|         this.connect('activate', () => this._openDialog()); | ||||
|     } | ||||
|  | ||||
|     run(arr) | ||||
|     { | ||||
|         arr = arr || []; | ||||
|         super.run(arr); | ||||
|     } | ||||
|  | ||||
|     _buildUI() | ||||
|     { | ||||
|         this.appWindow = new Gtk.ApplicationWindow({ | ||||
|             application: this, | ||||
|             title: APP_NAME, | ||||
|             border_width: 0, | ||||
|             resizable: true, | ||||
|             window_position: Gtk.WindowPosition.CENTER, | ||||
|             width_request: 960, | ||||
|             height_request: 642 | ||||
|         }); | ||||
|  | ||||
|         this.interface = new Interface(); | ||||
|  | ||||
|         this.appWindow.add(this.interface); | ||||
|         this.appWindow.connect('realize', this._onRealize.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _onRealize() | ||||
|     { | ||||
|         this.player = new Player(); | ||||
|         this.interface.addPlayer(this.player); | ||||
|  | ||||
|         this.player.widget.show_all(); | ||||
|         this.emit('player-ready', true); | ||||
|     } | ||||
|  | ||||
|     _openDialog() | ||||
|     { | ||||
|         this.appWindow.show_all(); | ||||
|     } | ||||
| }); | ||||
							
								
								
									
										92
									
								
								clapper_src/controls.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								clapper_src/controls.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| const { GObject, Gtk } = imports.gi; | ||||
|  | ||||
| var Controls = GObject.registerClass( | ||||
| class ClapperControls extends Gtk.HBox | ||||
| { | ||||
|     _init() | ||||
|     { | ||||
|         super._init({ | ||||
|             margin_top: 4, | ||||
|             margin_bottom: 4 | ||||
|         }); | ||||
|  | ||||
|         this.togglePlayButton = Gtk.Button.new_from_icon_name( | ||||
|             'media-playback-pause-symbolic', | ||||
|             Gtk.IconSize.LARGE_TOOLBAR | ||||
|         ); | ||||
|         this.pauseButton = Gtk.Button.new_from_icon_name( | ||||
|             'media-playback-start-symbolic', | ||||
|             Gtk.IconSize.LARGE_TOOLBAR | ||||
|         ); | ||||
|         this.playImage = this.pauseButton.image; | ||||
|         this.pauseImage = this.togglePlayButton.image; | ||||
|  | ||||
|         this.positionScale = new Gtk.Scale({ | ||||
|             orientation: Gtk.Orientation.HORIZONTAL, | ||||
|             value_pos: Gtk.PositionType.LEFT, | ||||
|             draw_value: false | ||||
|         }); | ||||
|  | ||||
|         this.volumeButton = new Gtk.ScaleButton({ | ||||
|             size: Gtk.IconSize.SMALL_TOOLBAR | ||||
|         }); | ||||
|         this._prepareVolumeButton(); | ||||
|  | ||||
|         this.pack_start(this.togglePlayButton, false, false, 4); | ||||
|         this.pack_start(this.positionScale, true, true, 0); | ||||
|         this.pack_start(this.volumeButton, false, false, 4); | ||||
|     } | ||||
|  | ||||
|     _prepareVolumeButton() | ||||
|     { | ||||
|         this.volumeButtonAdjustment = this.volumeButton.get_adjustment(); | ||||
|  | ||||
|         this.volumeButtonAdjustment.set_upper(2); | ||||
|         this.volumeButtonAdjustment.set_step_increment(0.05); | ||||
|         this.volumeButtonAdjustment.set_page_increment(0.05); | ||||
|  | ||||
|         let basicIcons = [ | ||||
|             "audio-volume-low-symbolic", | ||||
|             "audio-volume-medium-symbolic", | ||||
|             "audio-volume-medium-symbolic", | ||||
|             "audio-volume-high-symbolic" | ||||
|         ]; | ||||
|  | ||||
|         let iconsArr = [ | ||||
|             "audio-volume-muted-symbolic" | ||||
|         ]; | ||||
|  | ||||
|         for(let icon of basicIcons) | ||||
|             iconsArr = this._addManyToArr(icon, iconsArr, 5); | ||||
|  | ||||
|         iconsArr = this._addManyToArr( | ||||
|              "audio-volume-overamplified-symbolic", iconsArr, 18 | ||||
|         ); | ||||
|  | ||||
|         this.volumeButton.set_icons(iconsArr); | ||||
|  | ||||
|         let popup = this.volumeButton.get_popup(); | ||||
|         let box = popup.get_child(); | ||||
|         let boxChildren = box.get_children(); | ||||
|  | ||||
|         for(let child of boxChildren) { | ||||
|             if(child.constructor === Gtk.Button) | ||||
|                 box.remove(child); | ||||
|             if(child.constructor === Gtk.Scale) { | ||||
|                 child.height_request = 200; | ||||
|                 child.add_mark(0, Gtk.PositionType.LEFT, '0%'); | ||||
|                 child.add_mark(1, Gtk.PositionType.LEFT, '100%'); | ||||
|                 child.add_mark(2, Gtk.PositionType.LEFT, '200%'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _addManyToArr(item, arr, count) | ||||
|     { | ||||
|         for(let i = 0; i < count; i++) { | ||||
|             arr.push(item); | ||||
|         } | ||||
|  | ||||
|         return arr; | ||||
|     } | ||||
| }); | ||||
							
								
								
									
										124
									
								
								clapper_src/interface.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								clapper_src/interface.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| const { GObject, Gtk, GstPlayer } = imports.gi; | ||||
| const { Controls } = imports.clapper_src.controls; | ||||
|  | ||||
| var Interface = GObject.registerClass( | ||||
| class ClapperInterface extends Gtk.Grid | ||||
| { | ||||
|     _init() | ||||
|     { | ||||
|         super._init(); | ||||
|  | ||||
|         this.lastPositionValue = 0; | ||||
|  | ||||
|         this.controls = new Controls(); | ||||
|         this.attach(this.controls, 0, 1, 1, 1); | ||||
|     } | ||||
|  | ||||
|     addPlayer(player) | ||||
|     { | ||||
|         this._player = player; | ||||
|         this._player.widget.expand = true; | ||||
|         this._connectControlsToPlayer(); | ||||
|  | ||||
|         this.attach(this._player.widget, 0, 0, 1, 1); | ||||
|     } | ||||
|  | ||||
|     _connectControlsToPlayer() | ||||
|     { | ||||
|         this._player.connect('state-changed', this._onPlayerStateChanged.bind(this)); | ||||
|         this._player.connect('volume-changed', this._onPlayerVolumeChanged.bind(this)); | ||||
|         this._player.connect('duration-changed', this._onPlayerDurationChanged.bind(this)); | ||||
|         this._player.connect('position-updated', this._onPlayerPositionUpdated.bind(this)); | ||||
|  | ||||
|         this.controls.togglePlayButton.connect( | ||||
|             'clicked', this._onControlsTogglePlayClicked.bind(this) | ||||
|         ); | ||||
|         this.controls.positionScale.connect( | ||||
|             'value-changed', this._onControlsPositionChanged.bind(this) | ||||
|         ); | ||||
|         this.controls.volumeButton.connect( | ||||
|             'value-changed', this._onControlsVolumeChanged.bind(this) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     _onPlayerStateChanged(player, state) | ||||
|     { | ||||
|         switch(state) { | ||||
|             case GstPlayer.PlayerState.STOPPED: | ||||
|                 break; | ||||
|             case GstPlayer.PlayerState.BUFFERING: | ||||
|                 break; | ||||
|             case GstPlayer.PlayerState.PAUSED: | ||||
|                 this.controls.togglePlayButton.image = this.controls.playImage; | ||||
|                 break; | ||||
|             case GstPlayer.PlayerState.PLAYING: | ||||
|                 this.controls.togglePlayButton.image = this.controls.pauseImage; | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _onPlayerDurationChanged(player) | ||||
|     { | ||||
|         let duration = player.get_duration() / 1000000000; | ||||
|         let increment = (duration < 1) | ||||
|             ? 0 | ||||
|             : (duration < 100) | ||||
|             ? 1 | ||||
|             : duration / 100; | ||||
|  | ||||
|         let adjustment = new Gtk.Adjustment({ | ||||
|             upper: duration, | ||||
|             step_increment: increment, | ||||
|             page_increment: increment | ||||
|         }); | ||||
|         this.controls.positionScale.set_adjustment(adjustment); | ||||
|     } | ||||
|  | ||||
|     _onPlayerPositionUpdated(player, position) | ||||
|     { | ||||
|         let positionSeconds = position / 1000000000; | ||||
|         let positionFloor = Math.floor(positionSeconds); | ||||
|  | ||||
|         if(positionFloor === this.lastPositionValue) | ||||
|             return; | ||||
|  | ||||
|         this.lastPositionValue = positionFloor; | ||||
|         this.controls.positionScale.set_value(positionSeconds); | ||||
|     } | ||||
|  | ||||
|     _onPlayerVolumeChanged(player) | ||||
|     { | ||||
|         let volume = player.get_volume(); | ||||
|  | ||||
|         if(this.controls.volumeButton.value === volume) | ||||
|             return; | ||||
|  | ||||
|         this.controls.volumeButton.value = volume; | ||||
|     } | ||||
|  | ||||
|     _onControlsTogglePlayClicked() | ||||
|     { | ||||
|         this._player.toggle_play(); | ||||
|     } | ||||
|  | ||||
|     _onControlsPositionChanged(range) | ||||
|     { | ||||
|         let position = Math.floor(range.get_value()); | ||||
|  | ||||
|         if(position === this.lastPositionValue) | ||||
|             return; | ||||
|  | ||||
|         this.lastPositionValue = position; | ||||
|         this._player.seek_seconds(position); | ||||
|     } | ||||
|  | ||||
|     _onControlsVolumeChanged(widget, value) | ||||
|     { | ||||
|         if(this._player.get_volume() === value) | ||||
|             return; | ||||
|  | ||||
|         this._player.set_volume(value); | ||||
|     } | ||||
| }); | ||||
| @@ -1,10 +1,19 @@ | ||||
| const { GLib, GObject, Gst, GstPlayer } = imports.gi; | ||||
| 
 | ||||
| var GtkPlayer = GObject.registerClass( | ||||
| class GtkPlayer extends GstPlayer.Player | ||||
| const DEFAULTS = { | ||||
|     position_update_interval: 1000, | ||||
|     seek_accurate: false, | ||||
|     user_agent: 'clapper', | ||||
| }; | ||||
| 
 | ||||
| var Player = GObject.registerClass( | ||||
| class ClapperPlayer extends GstPlayer.Player | ||||
| { | ||||
|     _init() | ||||
|     _init(opts) | ||||
|     { | ||||
|         opts = opts || {}; | ||||
|         Object.assign(opts, DEFAULTS); | ||||
| 
 | ||||
|         let gtkglsink = Gst.ElementFactory.make('gtkglsink', null); | ||||
|         let glsinkbin = Gst.ElementFactory.make('glsinkbin', null); | ||||
|         glsinkbin.sink = gtkglsink; | ||||
| @@ -19,6 +28,13 @@ class GtkPlayer extends GstPlayer.Player | ||||
|             video_renderer: renderer | ||||
|         }); | ||||
| 
 | ||||
|         let config = this.get_config(); | ||||
| 
 | ||||
|         for(let setting of Object.keys(DEFAULTS)) | ||||
|             GstPlayer.Player[`config_set_${setting}`](config, opts[setting]); | ||||
| 
 | ||||
|         this.set_config(config); | ||||
| 
 | ||||
|         this.loop = GLib.MainLoop.new(null, false); | ||||
|         this.widget = gtkglsink.widget; | ||||
|         this.state = GstPlayer.PlayerState.STOPPED; | ||||
| @@ -33,6 +49,15 @@ class GtkPlayer extends GstPlayer.Player | ||||
|         this.seek(position * 1000000000); | ||||
|     } | ||||
| 
 | ||||
|     toggle_play() | ||||
|     { | ||||
|         let action = (this.state === GstPlayer.PlayerState.PLAYING) | ||||
|             ? 'pause' | ||||
|             : 'play'; | ||||
| 
 | ||||
|         this[action](); | ||||
|     } | ||||
| 
 | ||||
|     _onStateChanged(player, state) | ||||
|     { | ||||
|         this.state = state; | ||||
							
								
								
									
										5
									
								
								gex.json
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								gex.json
									
									
									
									
									
								
							| @@ -1,6 +1,9 @@ | ||||
| { | ||||
|   "name": "clapper", | ||||
|   "files": [ | ||||
|     "src/player.js" | ||||
|     "clapper_src/app.js", | ||||
|     "clapper_src/controls.js", | ||||
|     "clapper_src/interface.js", | ||||
|     "clapper_src/player.js" | ||||
|   ] | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user