diff --git a/clapper_src/app.js b/clapper_src/app.js index d72711bd..8bce6cf9 100644 --- a/clapper_src/app.js +++ b/clapper_src/app.js @@ -4,13 +4,9 @@ const { Widget } = imports.clapper_src.widget; const Debug = imports.clapper_src.debug; const Menu = imports.clapper_src.menu; const Misc = imports.clapper_src.misc; -const Shared = imports.clapper_src.shared; let { debug } = Debug; -let { settings } = Shared; - -const APP_NAME = 'Clapper'; -const APP_ID = 'com.github.rafostar.Clapper'; +let { settings } = Misc; var App = GObject.registerClass( class ClapperApp extends Gtk.Application @@ -18,7 +14,7 @@ class ClapperApp extends Gtk.Application _init(opts) { super._init({ - application_id: APP_ID + application_id: Misc.appId }); let defaults = { @@ -33,15 +29,15 @@ class ClapperApp extends Gtk.Application let window = new Gtk.ApplicationWindow({ application: this, - title: APP_NAME, + title: Misc.appName, }); - for(let action of Menu.actions) { + for(let action in Menu.actions) { let simpleAction = new Gio.SimpleAction({ - name: action.name + name: action }); - simpleAction.connect('activate', () => - action(this.active_window, APP_NAME) + simpleAction.connect( + 'activate', () => Menu.actions[action](this.active_window) ); this.add_action(simpleAction); } diff --git a/clapper_src/dialogs.js b/clapper_src/dialogs.js new file mode 100644 index 00000000..a4c6b66b --- /dev/null +++ b/clapper_src/dialogs.js @@ -0,0 +1,243 @@ +const { GObject, Gtk, Gst } = imports.gi; +const Debug = imports.clapper_src.debug; +const Misc = imports.clapper_src.misc; +const Prefs = imports.clapper_src.prefs; +const PrefsBase = imports.clapper_src.prefsBase; + +let { debug } = Debug; + +var FileChooser = GObject.registerClass( +class ClapperFileChooser extends Gtk.FileChooserNative +{ + _init(window) + { + super._init({ + transient_for: window, + modal: true, + }); + + let filter = new Gtk.FileFilter({ + name: 'Media Files', + }); + filter.add_mime_type('video/*'); + filter.add_mime_type('audio/*'); + filter.add_mime_type('application/claps'); + this.add_filter(filter); + + this.responseSignal = this.connect('response', this._onResponse.bind(this)); + + /* File chooser closes itself when nobody is holding its ref */ + this.ref(); + this.show(); + } + + _onResponse(filechooser, response) + { + debug('closing file chooser dialog'); + + this.disconnect(this.responseSignal); + this.responseSignal = null; + + if(response === Gtk.ResponseType.ACCEPT) { + let file = this.get_file(); + let { player } = this.get_transient_for().get_child(); + + player.set_media(file.get_uri()); + } + + this.run_dispose(); + } +}); + +var UriDialog = GObject.registerClass( +class ClapperUriDialog extends Gtk.Dialog +{ + _init(window) + { + super._init({ + transient_for: window, + destroy_with_parent: true, + modal: true, + title: 'Open URI', + default_width: 460, + }); + + let box = new Gtk.Box({ + orientation: Gtk.Orientation.HORIZONTAL, + valign: Gtk.Align.CENTER, + spacing: 6, + }); + box.add_css_class('uridialogbox'); + + let linkEntry = new Gtk.Entry({ + activates_default: true, + truncate_multiline: true, + width_request: 220, + height_request: 36, + hexpand: true, + }); + linkEntry.set_placeholder_text("Enter or drop URI here"); + linkEntry.connect('notify::text', this._onTextNotify.bind(this)); + box.append(linkEntry); + + let openButton = new Gtk.Button({ + label: "Open", + halign: Gtk.Align.END, + sensitive: false, + }); + openButton.connect('clicked', this._onOpenButtonClicked.bind(this)); + box.append(openButton); + + let area = this.get_content_area(); + area.append(box); + + this.closeSignal = this.connect('close-request', this._onCloseRequest.bind(this)); + this.show(); + } + + openUri(uri) + { + let { player } = this.get_transient_for().get_child(); + player.set_media(uri); + + this.close(); + } + + _onTextNotify(entry) + { + let isUriValid = (entry.text.length) + ? Gst.uri_is_valid(entry.text) + : false; + + let button = entry.get_next_sibling(); + button.set_sensitive(isUriValid); + } + + _onOpenButtonClicked(button) + { + let entry = button.get_prev_sibling(); + this.openUri(entry.text); + } + + _onCloseRequest(dialog) + { + debug('closing URI dialog'); + + dialog.disconnect(this.closeSignal); + this.closeSignal = null; + + dialog.run_dispose(); + } +}); + +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, + }); + + let pages = [ + { + title: 'Player', + pages: [ + { + title: 'General', + widget: Prefs.GeneralPage, + }, + { + title: 'Behaviour', + widget: Prefs.BehaviourPage, + } + ] + }, + { + title: 'Advanced', + pages: [ + { + title: 'GStreamer', + widget: Prefs.GStreamerPage, + } + ] + } + ]; + + let prefsNotebook = new PrefsBase.Notebook(pages); + prefsNotebook.add_css_class('prefsnotebook'); + + let 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; + + let area = dialog.get_content_area(); + let notebook = area.get_first_child(); + notebook._onClose(); + + dialog.run_dispose(); + } +}); + +var AboutDialog = GObject.registerClass( +class ClapperAboutDialog extends Gtk.AboutDialog +{ + _init(window) + { + let gstVer = [ + Gst.VERSION_MAJOR, Gst.VERSION_MINOR, Gst.VERSION_MICRO + ].join('.'); + + let gtkVer = [ + Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION + ].join('.'); + + let osInfo = [ + 'GTK version' + ': ' + gtkVer, + 'GStreamer version' + ': ' + gstVer + ].join('\n'); + + super._init({ + transient_for: window, + destroy_with_parent: true, + modal: true, + program_name: Misc.appName, + comments: 'A GNOME media player powered by GStreamer', + version: Misc.getClapperVersion(), + authors: ['Rafał Dzięgiel'], + artists: ['Rafał Dzięgiel'], + license_type: Gtk.License.GPL_3_0, + logo_icon_name: 'com.github.rafostar.Clapper', + website: 'https://github.com/Rafostar/clapper', + system_information: osInfo, + }); + + this.closeSignal = this.connect('close-request', this._onCloseRequest.bind(this)); + this.show(); + } + + _onCloseRequest(dialog) + { + debug('closing about dialog'); + + dialog.disconnect(this.closeSignal); + this.closeSignal = null; + + dialog.run_dispose(); + } +}); diff --git a/clapper_src/filechooser.js b/clapper_src/filechooser.js deleted file mode 100644 index 84b996fc..00000000 --- a/clapper_src/filechooser.js +++ /dev/null @@ -1,47 +0,0 @@ -const { GObject, Gtk } = imports.gi; - -var FileChooser = GObject.registerClass( -class ClapperFileChooser extends Gtk.FileChooserNative -{ - _init(window, appName) - { - super._init({ - transient_for: window, - modal: true, - }); - - let filter = new Gtk.FileFilter({ - name: 'Media Files', - }); - filter.add_mime_type('video/*'); - filter.add_mime_type('audio/*'); - filter.add_mime_type('application/claps'); - this.add_filter(filter); - - this.responseSignal = this.connect('response', this._onResponse.bind(this)); - } - - present() - { - /* File chooser closes itself when nobody is holding its ref */ - this.ref(); - - super.show(); - } - - _onResponse(filechooser, response) - { - this.disconnect(this.responseSignal); - this.responseSignal = null; - - if(response === Gtk.ResponseType.ACCEPT) { - let file = this.get_file(); - let { player } = this.get_transient_for().get_child(); - - player.set_media(file.get_uri()); - } - - this.unref(); - this.run_dispose(); - } -}); diff --git a/clapper_src/menu.js b/clapper_src/menu.js index 489757e5..0fb95f5f 100644 --- a/clapper_src/menu.js +++ b/clapper_src/menu.js @@ -1,79 +1,13 @@ const { GObject, Gst, Gtk } = imports.gi; -const Misc = imports.clapper_src.misc; -const Prefs = imports.clapper_src.prefs; -const { FileChooser } = imports.clapper_src.filechooser; -const { UriDialog } = imports.clapper_src.uridialog; +const Dialogs = imports.clapper_src.dialogs; -var actions = [ - openLocal, - openUri, - prefs, - about, -]; +var actions = { + openLocal: (window) => new Dialogs.FileChooser(window), + openUri: (window) => new Dialogs.UriDialog(window), + prefs: (window) => new Dialogs.PrefsDialog(window), + about: (window) => new Dialogs.AboutDialog(window), +}; var accels = [ ['app.quit', ['q']], ]; - -function openLocal(window, appName) -{ - let fileChooser = new FileChooser(window); - fileChooser.present(); -} - -function openUri(window, appName) -{ - let uriDialog = new UriDialog(window); - uriDialog.present(); -} - -function prefs(window, appName) -{ - let prefsWidget = Prefs.buildPrefsWidget(); - let prefsDialog = new Gtk.Dialog({ - title: 'Preferences', - modal: true, - transient_for: window, - child: prefsWidget, - default_width: 460, - default_height: 400, - }); - prefsDialog.connect('close-request', () => { - prefsWidget._onClose(); - prefsWidget.run_dispose(); - prefsDialog.run_dispose(); - }); - prefsDialog.present(); -} - -function about(window, appName) -{ - let gstVer = [ - Gst.VERSION_MAJOR, Gst.VERSION_MINOR, Gst.VERSION_MICRO - ].join('.'); - - let gtkVer = [ - Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION - ].join('.'); - - let osInfo = [ - 'GTK version' + ': ' + gtkVer, - 'GStreamer version' + ': ' + gstVer - ].join('\n'); - - let aboutDialog = new Gtk.AboutDialog({ - program_name: appName, - comments: 'A GNOME media player powered by GStreamer', - version: Misc.getClapperVersion(), - authors: ['Rafał Dzięgiel'], - artists: ['Rafał Dzięgiel'], - license_type: Gtk.License.GPL_3_0, - logo_icon_name: 'com.github.rafostar.Clapper', - website: 'https://github.com/Rafostar/clapper', - modal: true, - system_information: osInfo, - transient_for: window, - }); - aboutDialog.connect('close-request', () => aboutDialog.run_dispose()); - aboutDialog.present(); -} diff --git a/clapper_src/misc.js b/clapper_src/misc.js index a6516a83..d693689b 100644 --- a/clapper_src/misc.js +++ b/clapper_src/misc.js @@ -1,8 +1,15 @@ -const { GstPlayer, Gtk } = imports.gi; +const { Gio, GstPlayer, Gtk } = imports.gi; const Debug = imports.clapper_src.debug; -var clapperPath; -var clapperVersion; +var appName = 'Clapper'; +var appId = 'com.github.rafostar.Clapper'; + +var clapperPath = null; +var clapperVersion = null; + +var settings = new Gio.Settings({ + schema_id: appId, +}); let { debug } = Debug; let inhibitCookie; diff --git a/clapper_src/player.js b/clapper_src/player.js index 57773554..31635a29 100644 --- a/clapper_src/player.js +++ b/clapper_src/player.js @@ -1,11 +1,11 @@ const { Gdk, Gio, GLib, GObject, Gst, GstPlayer, Gtk } = imports.gi; const ByteArray = imports.byteArray; -const { PlayerBase } = imports.clapper_src.playerBase; const Debug = imports.clapper_src.debug; -const Shared = imports.clapper_src.shared; +const Misc = imports.clapper_src.misc; +const { PlayerBase } = imports.clapper_src.playerBase; let { debug } = Debug; -let { settings } = Shared; +let { settings } = Misc; var Player = GObject.registerClass( class ClapperPlayer extends PlayerBase @@ -16,20 +16,19 @@ class ClapperPlayer extends PlayerBase this.state = GstPlayer.PlayerState.STOPPED; this.cursorInPlayer = false; - this.playOnFullscreen = false; this.is_local_file = false; this.seek_done = true; this.dragAllowed = false; this.isWidgetDragging = false; this.doneStartup = false; + this.playOnFullscreen = false; + this.quitOnStop = false; + this.posX = 0; this.posY = 0; this.keyPressCount = 0; - this._playerSignals = []; - this._widgetSignals = []; - this._playlist = []; this._trackId = 0; @@ -62,11 +61,11 @@ class ClapperPlayer extends PlayerBase motionController.connect('motion', this._onWidgetMotion.bind(this)); this.widget.add_controller(motionController); - this.selfConnect('state-changed', this._onStateChanged.bind(this)); - this.selfConnect('uri-loaded', this._onUriLoaded.bind(this)); - this.selfConnect('end-of-stream', this._onStreamEnded.bind(this)); - this.selfConnect('warning', this._onPlayerWarning.bind(this)); - this.selfConnect('error', this._onPlayerError.bind(this)); + this.connect('state-changed', this._onStateChanged.bind(this)); + this.connect('uri-loaded', this._onUriLoaded.bind(this)); + this.connect('end-of-stream', this._onStreamEnded.bind(this)); + this.connect('warning', this._onPlayerWarning.bind(this)); + this.connect('error', this._onPlayerError.bind(this)); this._realizeSignal = this.widget.connect('realize', this._onWidgetRealize.bind(this)); } @@ -242,13 +241,6 @@ class ClapperPlayer extends PlayerBase this[action](); } - selfConnect(signal, fn) - { - this._playerSignals.push( - super.connect(signal, fn) - ); - } - _setHideCursorTimeout() { this._clearTimeout('hideCursor'); @@ -317,10 +309,16 @@ class ClapperPlayer extends PlayerBase { this.state = state; - let clapperWidget = this.widget.get_ancestor(Gtk.Grid); + if(this.quitOnStop && state === GstPlayer.PlayerState.STOPPED) { + let root = player.widget.get_root(); + + return root.run_dispose(); + } + + let clapperWidget = player.widget.get_ancestor(Gtk.Grid); if(!clapperWidget) return; - if(!this.seek_done && this.state !== GstPlayer.PlayerState.BUFFERING) { + if(!this.seek_done && state !== GstPlayer.PlayerState.BUFFERING) { clapperWidget.updateTime(); this.seek_done = true; debug('seeking finished'); @@ -450,7 +448,6 @@ class ClapperPlayer extends PlayerBase case Gdk.KEY_Q: let root = this.widget.get_root(); root.emit('close-request'); - root.destroy(); break; default: break; @@ -598,15 +595,6 @@ class ClapperPlayer extends PlayerBase _onCloseRequest(window) { - while(this._widgetSignals.length) - this.widget.disconnect(this._widgetSignals.pop()); - - while(this._playerSignals.length) - this.disconnect(this._playerSignals.pop()); - - if(this.state !== GstPlayer.PlayerState.STOPPED) - this.stop(); - let clapperWidget = this.widget.get_ancestor(Gtk.Grid); if(!clapperWidget.fullscreenMode && !clapperWidget.floatingMode) { let size = window.get_size(); @@ -616,7 +604,10 @@ class ClapperPlayer extends PlayerBase } } - let app = window.get_application(); - if(app) app.quit(); + if(this.state === GstPlayer.PlayerState.STOPPED) + return window.run_dispose(); + + this.quitOnStop = true; + this.stop(); } }); diff --git a/clapper_src/playerBase.js b/clapper_src/playerBase.js index 374976d0..c74474fc 100644 --- a/clapper_src/playerBase.js +++ b/clapper_src/playerBase.js @@ -1,6 +1,6 @@ const { Gio, GLib, GObject, Gst, GstPlayer, Gtk } = imports.gi; const Debug = imports.clapper_src.debug; -const Shared = imports.clapper_src.shared; +const Misc = imports.clapper_src.misc; /* PlayFlags are not exported through GI */ Gst.PlayFlags = { @@ -20,7 +20,7 @@ Gst.PlayFlags = { }; let { debug } = Debug; -let { settings } = Shared; +let { settings } = Misc; var PlayerBase = GObject.registerClass( class ClapperPlayerBase extends GstPlayer.Player diff --git a/clapper_src/prefs.js b/clapper_src/prefs.js index 8a182d06..c3a37655 100644 --- a/clapper_src/prefs.js +++ b/clapper_src/prefs.js @@ -1,10 +1,10 @@ const { GObject, Gtk, Pango } = imports.gi; +const Misc = imports.clapper_src.misc; const PrefsBase = imports.clapper_src.prefsBase; -const Shared = imports.clapper_src.shared; -let { settings } = Shared; +let { settings } = Misc; -let GeneralPage = GObject.registerClass( +var GeneralPage = GObject.registerClass( class ClapperGeneralPage extends PrefsBase.Grid { _init() @@ -31,7 +31,7 @@ class ClapperGeneralPage extends PrefsBase.Grid } }); -let BehaviourPage = GObject.registerClass( +var BehaviourPage = GObject.registerClass( class ClapperBehaviourPage extends PrefsBase.Grid { _init() @@ -53,7 +53,7 @@ class ClapperBehaviourPage extends PrefsBase.Grid } }); -let GStreamerPage = GObject.registerClass( +var GStreamerPage = GObject.registerClass( class ClapperGStreamerPage extends PrefsBase.Grid { _init() @@ -241,36 +241,3 @@ class ClapperGStreamerPage extends PrefsBase.Grid this.settingsChangedSignal = null; } }); - -function buildPrefsWidget() -{ - let pages = [ - { - title: 'Player', - pages: [ - { - title: 'General', - widget: GeneralPage, - }, - { - title: 'Behaviour', - widget: BehaviourPage, - } - ] - }, - { - title: 'Advanced', - pages: [ - { - title: 'GStreamer', - widget: GStreamerPage, - } - ] - } - ]; - - let prefsNotebook = new PrefsBase.Notebook(pages); - prefsNotebook.add_css_class('prefsnotebook'); - - return prefsNotebook; -} diff --git a/clapper_src/prefsBase.js b/clapper_src/prefsBase.js index 6b0c8696..4bbc4b8b 100644 --- a/clapper_src/prefsBase.js +++ b/clapper_src/prefsBase.js @@ -1,9 +1,9 @@ const { Gio, GObject, Gtk } = imports.gi; const Debug = imports.clapper_src.debug; -const Shared = imports.clapper_src.shared; +const Misc = imports.clapper_src.misc; let { debug } = Debug; -let { settings } = Shared; +let { settings } = Misc; var Notebook = GObject.registerClass( class ClapperPrefsNotebook extends Gtk.Notebook diff --git a/clapper_src/shared.js b/clapper_src/shared.js deleted file mode 100644 index d436c086..00000000 --- a/clapper_src/shared.js +++ /dev/null @@ -1,5 +0,0 @@ -const { Gio } = imports.gi; - -var settings = new Gio.Settings({ - schema_id: 'com.github.rafostar.Clapper' -}); diff --git a/clapper_src/uridialog.js b/clapper_src/uridialog.js deleted file mode 100644 index c224bc9e..00000000 --- a/clapper_src/uridialog.js +++ /dev/null @@ -1,67 +0,0 @@ -const { GObject, Gtk, Gst } = imports.gi; - -var UriDialog = GObject.registerClass( -class ClapperUriDialog extends Gtk.Dialog -{ - _init(window, appName) - { - super._init({ - transient_for: window, - title: 'Open URI', - default_width: 460, - modal: true, - }); - - let box = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - valign: Gtk.Align.CENTER, - spacing: 6, - }); - box.add_css_class('uridialogbox'); - - let linkEntry = new Gtk.Entry({ - activates_default: true, - truncate_multiline: true, - width_request: 220, - height_request: 36, - hexpand: true, - }); - linkEntry.set_placeholder_text("Enter or drop URI here"); - linkEntry.connect('notify::text', this._onTextNotify.bind(this)); - box.append(linkEntry); - - let openButton = new Gtk.Button({ - label: "Open", - halign: Gtk.Align.END, - sensitive: false, - }); - openButton.connect('clicked', this._onOpenButtonClicked.bind(this)); - box.append(openButton); - - this.set_child(box); - } - - openUri(uri) - { - let { player } = this.get_transient_for().get_child(); - player.set_media(uri); - - this.close(); - } - - _onTextNotify(entry) - { - let isUriValid = (entry.text.length) - ? Gst.uri_is_valid(entry.text) - : false; - - let button = entry.get_next_sibling(); - button.set_sensitive(isUriValid); - } - - _onOpenButtonClicked(button) - { - let entry = button.get_prev_sibling(); - this.openUri(entry.text); - } -}); diff --git a/clapper_src/widget.js b/clapper_src/widget.js index c799528f..3fc06112 100644 --- a/clapper_src/widget.js +++ b/clapper_src/widget.js @@ -57,9 +57,9 @@ var Widget = GObject.registerClass({ this.mapSignal = this.connect('map', this._onMap.bind(this)); this.player = new Player(); - this.player.selfConnect('position-updated', this._onPlayerPositionUpdated.bind(this)); - this.player.selfConnect('duration-changed', this._onPlayerDurationChanged.bind(this)); - this.player.selfConnect('volume-changed', this._onPlayerVolumeChanged.bind(this)); + this.player.connect('position-updated', this._onPlayerPositionUpdated.bind(this)); + this.player.connect('duration-changed', this._onPlayerDurationChanged.bind(this)); + this.player.connect('volume-changed', this._onPlayerVolumeChanged.bind(this)); this.overlay.set_child(this.player.widget); this.overlay.add_overlay(this.revealerTop);