From 5dbdc178057bba3c24d98e957ea4754ad49fb8c2 Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 04:47:52 -0800 Subject: [PATCH 1/9] Add FPS, pos, horizontal flip options --- .idea/.gitignore | 5 + .idea/discord.xml | 7 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ .idea/visualizer.iml | 12 +++ src/metadata.json | 6 +- src/prefs.js | 102 ++++++++++++------ src/schemas/gschemas.compiled | Bin 0 -> 952 bytes ...me.shell.extensions.visualizer.gschema.xml | 51 ++++++--- src/visual.js | 74 ++++++++++--- 10 files changed, 204 insertions(+), 67 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/discord.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/visualizer.iml create mode 100644 src/schemas/gschemas.compiled diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..8bfbed1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/visualizer.iml b/.idea/visualizer.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/visualizer.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/metadata.json b/src/metadata.json index 7991f79..2325d8f 100644 --- a/src/metadata.json +++ b/src/metadata.json @@ -1,6 +1,6 @@ { "_generated": "Generated by SweetTooth, do not edit", - "description": "A Real Time Sound Visualizer Based On Gstreamer", + "description": "A Real Time Sound Visualizer Based On Gstreamer\nFor any Issues,Bugs and Suggestions please open an issue on Github", "name": "Sound Visualizer", "settings-schema": "org.gnome.shell.extensions.visualizer", "shell-version": [ @@ -13,5 +13,5 @@ ], "url": "https://github.com/raihan2000/visualizer", "uuid": "visualizer@sound.org", - "version": 4 -} + "version": 5 +} \ No newline at end of file diff --git a/src/prefs.js b/src/prefs.js index c9e5226..50d83e6 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -23,40 +23,55 @@ function buildPrefsWidget() { return widget; } + + const prefsWidget = GObject.registerClass( - class prefsWidget extends Gtk.Notebook { - - _init(params) { - super._init(params); - this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.visualizer'); - this.margin = 20; - - let grid = new Gtk.Grid(); - attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer' }), getSwitch('flip-visualizer', this._settings), 0); - attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings), 1); - attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings), 2); - attachItems(grid, new Gtk.Label({ label: 'Spects Line Width' }), getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings), 3); - attachItems(grid, new Gtk.Label({ label: 'Change Spects Band to Get' }), getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings), 4); - this.attachHybridRow(grid, new Gtk.Label({ label: 'Override Spect Value' }), new Gtk.Label({ label: 'Set Spects Value' }), getSwitch('spect-over-ride-bool', this._settings), getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings), 5); - this.append_page(grid, new Gtk.Label({ label: 'Visualizer' })); - let aboutBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); - if (major < 40) { - aboutBox.add(new Gtk.Label({ label: Me.metadata.name })); - aboutBox.add(new Gtk.Label({ label: 'Version: ' + Me.metadata.version.toString() })); - } else { - aboutBox.append(new Gtk.Label({ label: Me.metadata.name })); - aboutBox.append(new Gtk.Label({ label: 'Version: ' + Me.metadata.version.toString() })); + class prefsWidget extends Gtk.Notebook { + + _init(params) { + super._init(params); + this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.visualizer'); + this.margin = 20; + + let grid = new Gtk.Grid(); + let nextRow = 0; + let fpsOptions = new Gtk.ComboBoxText(); + ["15", "30", "60", "90", "120"].forEach(fps => fpsOptions.append_text(fps)); + fpsOptions.connect('changed', (widget) => { + let fps = widget.get_active_text(); + this._settings.set_int('fps', parseInt(fps, 10)); + }); + let currentFps = this._settings.get_int('fps'); + fpsOptions.set_active_id(currentFps.toString()); + attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer' }), getSwitch('flip-visualizer', this._settings), 0); + attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer Horizontally' }), getSwitch('horizontal-flip', this._settings), 0); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings), 1); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings), 1); + attachItems(grid, new Gtk.Label({ label: 'Visualizer X Position' }), getSpinButton(false, 'visualizer-pos-x', 0, 1920, 1, this._settings), 2); // Todo: Add multi-resolution support by checking screen size; Modify max to add or subtract by height/width based on flip status + attachItems(grid, new Gtk.Label({ label: 'Visualizer Y Position' }), getSpinButton(false, 'visualizer-pos-y', 0, 1080, 1, this._settings), 2); + attachItems(grid, new Gtk.Label({ label: 'Spects Line Width' }), getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings), 4); + attachItems(grid, new Gtk.Label({ label: 'Change Spects Band to Get' }), getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings), 3); + attachItems(grid, new Gtk.Label({ label: 'Frames Per Second (FPS)' }), getDropDown(this._settings), 6); + this.attachHybridRow(grid, new Gtk.Label({ label: 'Override Spect Value' }), new Gtk.Label({ label: 'Set Spects Value' }), getSwitch('spect-over-ride-bool', this._settings), getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings), 5); + this.append_page(grid, new Gtk.Label({ label: 'Visualizer' })); + let aboutBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); + if (major < 40) { + aboutBox.add(new Gtk.Label({ label: Me.metadata.name })); + aboutBox.add(new Gtk.Label({ label: 'Version: ' + Me.metadata.version.toString() })); + } else { + aboutBox.append(new Gtk.Label({ label: Me.metadata.name })); + aboutBox.append(new Gtk.Label({ label: 'Version: ' + Me.metadata.version.toString() })); + } + this.append_page(aboutBox, new Gtk.Label({ label: 'About' })); } - this.append_page(aboutBox, new Gtk.Label({ label: 'About' })); - } - attachHybridRow(grid, label, label1, button, button1, row) { - grid.attach(label, 0, row, 1, 1); - grid.attach(button, 1, row, 1, 1); - grid.attach(label1, 0, row + 1, 1, 1); - grid.attach(button1, 1, row + 1, 1, 1); - } - }); + attachHybridRow(grid, label, label1, button, button1, row) { + grid.attach(label, 0, row, 1, 1); + grid.attach(button, 1, row, 1, 1); + grid.attach(label1, 0, row + 1, 1, 1); + grid.attach(button1, 1, row + 1, 1, 1); + } + }); class PrefsWindow { constructor(window) { @@ -152,11 +167,15 @@ class PrefsWindow { fillPrefsWindow() { let visualWidget = this.create_page('Visualizer'); { let groupVisual = this.create_group(visualWidget); - this.append_row(groupVisual, 'Flip the Visualizer', getSwitch('flip-visualizer', this._settings)); + this.append_row(groupVisual, 'Flip the Visualizer Vertically', getSwitch('flip-visualizer', this._settings)); + this.append_row(groupVisual, 'Flip the Visualizer Horizontally', getSwitch('horizontal-flip', this._settings)); this.append_row(groupVisual, 'Visualizer Height', getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings)); this.append_row(groupVisual, 'Visualizer Width', getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings)); + this.append_row(groupVisual, 'Visualizer X Position', getSpinButton(false, 'visualizer-pos-x', 0, 1920, 1, this._settings)); + this.append_row(groupVisual, 'Visualizer Y Position', getSpinButton(false, 'visualizer-pos-y', 0, 1080, 1, this._settings)); this.append_row(groupVisual, 'Spects Line Width', getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings)); this.append_row(groupVisual, 'Change Spects Band to Get', getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings)); + this.append_row(groupVisual, 'Frames Per Second (FPS)', getDropDown(this._settings)); this.append_expander_row(groupVisual, 'Override Spect Value', 'Set Spects Value', 'spect-over-ride-bool', getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings)); } @@ -188,3 +207,22 @@ function getSpinButton(is_double, key, min, max, step, settings) { settings.bind(key, spin, 'value', Gio.SettingsBindFlags.DEFAULT); return spin; } + +function getDropDown(settings) { + let dropDown = new Gtk.ComboBoxText(); + let fpsValues = ["15", "30", "60", "90", "120"]; + fpsValues.forEach(fps => dropDown.append_text(fps)); + + dropDown.connect('changed', (widget) => { + let fps = widget.get_active_text(); + settings.set_int('fps', parseInt(fps, 10)); + }); + + let currentFps = settings.get_int('fps').toString(); + let currentIndex = fpsValues.indexOf(currentFps); + if (currentIndex !== -1) { + dropDown.set_active(currentIndex); + } + + return dropDown; +} \ No newline at end of file diff --git a/src/schemas/gschemas.compiled b/src/schemas/gschemas.compiled new file mode 100644 index 0000000000000000000000000000000000000000..59532df53b7a2c7f2c6ff15db3b18166a7f84467 GIT binary patch literal 952 zcmZuvziSjh7@e4$zs_GF38WH1BYVQ^rc8O=rHG(K%n2#7mz&&!uQ%TB{DJ*OPrW0(=e?Tm))c59YS(OaDeQ)13~aKF-$~3<<=aTbv9Ef$N~|`C^}E_` zhOypO8R9U!YeRPHCZPXD1^?%P3&6z@E`ff~lkgY7 zb)Yd=eNUhII{XLVWngRW^Ho|^j~gFgW)x7Y5_ zr@jII3wQuDM?N+EAK;(B@y>3QcS~J?k0Qi9U~vDd+lQL*b?_qaYkYo&`&0A$P4F7f zKb(3=pLz;@5BwZ>^)2~MpPKRS!27`C%KSt6)I9$o_z2iYt+)wac)C_Tl#G<_L`9># z9nD83)7vJ=!&q*_I_08P&8BKSm!_*Snd!EYEn{NFyMcMIYZ@?07MB5}6;}biHG7Be zTD&>mIX6t(=IDNRgf}SC)!=zr*J`{wS!Q5JagSEUI#ESV-VgKr E0sptYHvj+t literal 0 HcmV?d00001 diff --git a/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml b/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml index c20986b..c0b7f41 100644 --- a/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml +++ b/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml @@ -8,25 +8,13 @@ Location of visualizer - - 150 - Vertical Size of DrawingArea - - - 720 - Horizontal Size of DrawingArea - - - 5 - All Spect Bands width - - - 64 - Count Total Spects Bands - false - Flip Visualizer + Flip Visualizer Vertically + + + false + Flip Visualizer Horizontally false @@ -38,5 +26,34 @@ Override Spects Bands Override Spects Bands + + 30 + Frames Per Second + The number of frames per second for the visualizer. Possible values are 15, 30, 60, 90, and 120. + + + 5 + All Spect Bands width + + + 64 + Count Total Spects Bands + + + 150 + Vertical Size of DrawingArea + + + 720 + Horizontal Size of DrawingArea + + + 0 + Horizontal Position of DrawingArea + + + 0 + Vertical Position of DrawingArea + diff --git a/src/visual.js b/src/visual.js index cd335d8..95de693 100644 --- a/src/visual.js +++ b/src/visual.js @@ -10,16 +10,26 @@ const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); var Visualizer = GObject.registerClass( class musicVisualizer extends St.BoxLayout { _init() { + this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.visualizer'); super._init({ reactive: true, track_hover: true, can_focus: true }); + this._settings.connect('changed::fps', () => { + let fps = this._settings.get_int('fps'); + this._refreshRate = 1000 / fps; + this.updateGstInterval(); + this.startRefreshLoop(); + }); + this._settings.connect('changed::horizontal-flip', () => this._updateFlipSettings()); + this._settings.connect('changed::visualizer-pos-x', () => this.setPosition()); + this._settings.connect('changed::visualizer-pos-y', () => this.setPosition()); + let fps = this._settings.get_int('fps'); this._visualMenuManager = new PopupMenu.PopupMenuManager(this); this._freq = []; this._actor = new St.DrawingArea(); this.add_child(this._actor); - this._settings = ExtensionUtils.getSettings(); this.settingsChanged(); this._draggable = DND.makeDraggable(this); this._draggable._animateDragEnd = (eventTime) => { @@ -36,8 +46,34 @@ var Visualizer = GObject.registerClass( this.getMenuItems(); this._update(); this.setPosition(); + this._refreshRate = 1000 / fps; + this._refreshLoopId = null; + this.startRefreshLoop(); Main.layoutManager._backgroundGroup.add_child(this); } + + startRefreshLoop() { + if (this._refreshLoopId !== null) { + GLib.Source.remove(this._refreshLoopId); + } + this._refreshLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._refreshRate, () => { + this._actor.queue_repaint(); + return true; + }); + } + + updateGstInterval() { + let fps = this._settings.get_int('fps'); + let interval = 1000000000 / fps; + if (this._spectrum) { + this._spectrum.set_property("interval", interval); + } + } + + _updateFlipSettings() { + this._horizontalFlip = this._settings.get_boolean('horizontal-flip'); + this._update(); + } setupGst() { Gst.init(null); @@ -47,6 +83,7 @@ var Visualizer = GObject.registerClass( this._spectrum.set_property("bands", this._spectBands); this._spectrum.set_property("threshold", -80); this._spectrum.set_property("post-messages", true); + this.updateGstInterval(); let _sink = Gst.ElementFactory.make("fakesink", "sink"); this._pipeline.add(this._src); this._pipeline.add(this._spectrum); @@ -81,25 +118,28 @@ var Visualizer = GObject.registerClass( } drawStuff(area) { - let values = this.getSpectBands(); let [width, height] = area.get_surface_size(); let cr = area.get_context(); + let values = this.getSpectBands(); let lineW = this._settings.get_int('spects-line-width'); - let flip = this._settings.get_boolean('flip-visualizer'); + let horizontal_flip = this._settings.get_boolean('horizontal-flip'); + let vertical_flip = this._settings.get_boolean('flip-visualizer'); + + cr.setLineWidth(lineW); + for (let i = 0; i < values; i++) { - cr.setSourceRGBA(1, this._freq[i] / 80, 1, 1); - cr.setLineWidth(lineW); - if (!flip) { - cr.moveTo(lineW / 2 + i * width / values, height); - cr.lineTo(lineW / 2 + i * width / values, height - 1); - cr.lineTo(lineW / 2 + i * width / values, height * this._freq[i] / 80); - } else { - cr.moveTo(lineW / 2 + i * width / values, 0); - cr.lineTo(lineW / 2 + i * width / values, 1); - cr.lineTo(lineW / 2 + i * width / values, height / 80 * (80 - this._freq[i])); - } + let colorIntensity = this._freq[i] / 80; + cr.setSourceRGBA(1, colorIntensity, 1, 1); + + let xPosition = horizontal_flip ? width - (lineW / 2 + i * width / values) : lineW / 2 + i * width / values; + let yPosition = vertical_flip ? height / 80 * (80 - this._freq[i]) : height * this._freq[i] / 80; + + cr.moveTo(xPosition, vertical_flip ? 0 : height); + cr.lineTo(xPosition, vertical_flip ? 1 : height - 1); + cr.lineTo(xPosition, yPosition); cr.stroke(); } + cr.$dispose(); } @@ -145,7 +185,8 @@ var Visualizer = GObject.registerClass( setPosition() { if (this._ignorePositionUpdate) return; - let [x, y] = this._settings.get_value('visualizer-location').deep_unpack(); + let x = this._settings.get_int('visualizer-pos-x'); + let y = this._settings.get_int('visualizer-pos-y'); this.set_position(x, y); if (!this.get_parent()) return; @@ -323,6 +364,9 @@ var Visualizer = GObject.registerClass( } onDestroy() { + if (this._refreshLoopId !== null) { + GLib.Source.remove(this._refreshLoopId); + } this._removeSource(this._menuTimeoutId); this._removeSource(this._streamId); this._removeSource(this._defaultSrcId); From 6909583c900443f6e24a23ea80e3f763f012afa3 Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 04:51:59 -0800 Subject: [PATCH 2/9] Add gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file From aa8b541b80e30ba3248542f97f24993aa16da07c Mon Sep 17 00:00:00 2001 From: Vitaly Vakhteev Date: Sat, 30 Dec 2023 04:52:49 -0800 Subject: [PATCH 3/9] Delete .idea directory --- .idea/.gitignore | 5 ----- .idea/discord.xml | 7 ------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ .idea/visualizer.iml | 12 ------------ 5 files changed, 38 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/discord.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/visualizer.iml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index d8e9561..0000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 8bfbed1..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/visualizer.iml b/.idea/visualizer.iml deleted file mode 100644 index 24643cc..0000000 --- a/.idea/visualizer.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file From 3956ce101ba607512b750dd40295a9eeb879574f Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 14:21:40 -0800 Subject: [PATCH 4/9] Add color options, remove x, y pos --- README.md | 23 ++++---- src/prefs.js | 53 +++++++++++++----- src/schemas/gschemas.compiled | Bin 952 -> 892 bytes ...me.shell.extensions.visualizer.gschema.xml | 13 ++--- src/visual.js | 26 ++++++--- 5 files changed, 74 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index a689aff..5396b85 100644 --- a/README.md +++ b/README.md @@ -3,25 +3,26 @@ A Sound Visualizer for Gnome Shell based on Gstreamer specially for Wayland ![demo](assets/visualization.gif) -For Desktop Widgets I'm Using [Circular Widgets](https://extensions.gnome.org/extension/5530/circular-widgets/) Extension. +For the Desktop Widgets, I'm using the [Circular Widgets](https://extensions.gnome.org/extension/5530/circular-widgets/) extension. # Features -- Drag and Drop Supports -- Change Audio source from Menu (To change right/left click on Visualizer) -- Change Visualizer size +- Drag and Drop Support +- Change Audio Source from the Menu (To change right/left click on Visualizer) +- Change Visualizer Size - Increase or Decrease Bands -- Choose how many bands will appear on display -- Now you can Flip Visualizer -- Added older version Gnome Shell v3.36 to v43.0 +- Flip Visualizer Horizontally or Vertically +- Ability to Change the FPS of the Visualizer +- Ability to choose how many bands will appear on display +- Added older version Gnome Shell support, from v3.36 to v43.0 -More Feature will be added in Future +More features will be added in the future # Installation -1. Download zip file : https://github.com/raihan2000/visualizer/archive/refs/heads/main.zip +1. Download the zip file : https://github.com/raihan2000/visualizer/archive/refs/heads/main.zip 2. Extract to visualizer-main -4. make install +3. `make install` or @@ -33,4 +34,4 @@ make install # Credits -This Extension is inspired by [Glava](https://github.com/jarcode-foss/glava) +This extension is inspired by [Glava](https://github.com/jarcode-foss/glava). diff --git a/src/prefs.js b/src/prefs.js index 50d83e6..5b41688 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -23,6 +23,22 @@ function buildPrefsWidget() { return widget; } +function updatePositionMaxes() { + let visualizerWidth = this._settings.get_int('visualizer-width'); + let visualizerHeight = this._settings.get_int('visualizer-height'); + + let display = Gdk.Display.get_default(); + let monitor = display.get_primary_monitor(); + let geometry = monitor.get_geometry(); + let screenWidth = geometry.width; + let screenHeight = geometry.height; + + let maxX = screenWidth - visualizerWidth; + let maxY = screenHeight - visualizerHeight; + + this.visualizerXSpin.set_range(0, maxX); + this.visualizerYSpin.set_range(0, maxY); +} const prefsWidget = GObject.registerClass( @@ -34,7 +50,6 @@ const prefsWidget = GObject.registerClass( this.margin = 20; let grid = new Gtk.Grid(); - let nextRow = 0; let fpsOptions = new Gtk.ComboBoxText(); ["15", "30", "60", "90", "120"].forEach(fps => fpsOptions.append_text(fps)); fpsOptions.connect('changed', (widget) => { @@ -44,15 +59,14 @@ const prefsWidget = GObject.registerClass( let currentFps = this._settings.get_int('fps'); fpsOptions.set_active_id(currentFps.toString()); attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer' }), getSwitch('flip-visualizer', this._settings), 0); - attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer Horizontally' }), getSwitch('horizontal-flip', this._settings), 0); - attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings), 1); - attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings), 1); - attachItems(grid, new Gtk.Label({ label: 'Visualizer X Position' }), getSpinButton(false, 'visualizer-pos-x', 0, 1920, 1, this._settings), 2); // Todo: Add multi-resolution support by checking screen size; Modify max to add or subtract by height/width based on flip status - attachItems(grid, new Gtk.Label({ label: 'Visualizer Y Position' }), getSpinButton(false, 'visualizer-pos-y', 0, 1080, 1, this._settings), 2); - attachItems(grid, new Gtk.Label({ label: 'Spects Line Width' }), getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings), 4); - attachItems(grid, new Gtk.Label({ label: 'Change Spects Band to Get' }), getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings), 3); - attachItems(grid, new Gtk.Label({ label: 'Frames Per Second (FPS)' }), getDropDown(this._settings), 6); - this.attachHybridRow(grid, new Gtk.Label({ label: 'Override Spect Value' }), new Gtk.Label({ label: 'Set Spects Value' }), getSwitch('spect-over-ride-bool', this._settings), getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings), 5); + attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer Horizontally' }), getSwitch('horizontal-flip', this._settings), 1); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings), 2); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings), 3); + attachItems(grid, new Gtk.Label({ label: 'Spects Line Width' }), getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings), 5); + attachItems(grid, new Gtk.Label({ label: 'Change Spects Band to Get' }), getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings), 4); + attachItems(grid, new Gtk.Label({ label: 'Frames Per Second (FPS)' }), getDropDown(this._settings), 7); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Color' }), getColorButton(this._settings), 8); + this.attachHybridRow(grid, new Gtk.Label({ label: 'Override Spect Value' }), new Gtk.Label({ label: 'Set Spects Value' }), getSwitch('spect-over-ride-bool', this._settings), getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings), 6); this.append_page(grid, new Gtk.Label({ label: 'Visualizer' })); let aboutBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); if (major < 40) { @@ -171,11 +185,10 @@ class PrefsWindow { this.append_row(groupVisual, 'Flip the Visualizer Horizontally', getSwitch('horizontal-flip', this._settings)); this.append_row(groupVisual, 'Visualizer Height', getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings)); this.append_row(groupVisual, 'Visualizer Width', getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings)); - this.append_row(groupVisual, 'Visualizer X Position', getSpinButton(false, 'visualizer-pos-x', 0, 1920, 1, this._settings)); - this.append_row(groupVisual, 'Visualizer Y Position', getSpinButton(false, 'visualizer-pos-y', 0, 1080, 1, this._settings)); this.append_row(groupVisual, 'Spects Line Width', getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings)); this.append_row(groupVisual, 'Change Spects Band to Get', getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings)); this.append_row(groupVisual, 'Frames Per Second (FPS)', getDropDown(this._settings)); + this.append_row(groupVisual, 'Visualizer Color', getColorButton(this._settings)); this.append_expander_row(groupVisual, 'Override Spect Value', 'Set Spects Value', 'spect-over-ride-bool', getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings)); } @@ -223,6 +236,20 @@ function getDropDown(settings) { if (currentIndex !== -1) { dropDown.set_active(currentIndex); } - return dropDown; +} + +function getColorButton(settings) { + let button = new Gtk.ColorButton(); + let rgbaString = settings.get_string('visualizer-color'); + let rgbaParts = rgbaString.split(',').map(parseFloat); + let gdkRGBA = new Gdk.RGBA({red: rgbaParts[0], green: rgbaParts[1], blue: rgbaParts[2], alpha: rgbaParts[3]}); + button.set_rgba(gdkRGBA); + button.connect('color-set', () => { + let gdkRGBA = button.get_rgba(); + let rgbaString = `${gdkRGBA.red},${gdkRGBA.green},${gdkRGBA.blue},${gdkRGBA.alpha}`; + settings.set_string('visualizer-color', rgbaString); + }); + + return button; } \ No newline at end of file diff --git a/src/schemas/gschemas.compiled b/src/schemas/gschemas.compiled index 59532df53b7a2c7f2c6ff15db3b18166a7f84467..ea68312938c8b97892440daff6c381c7bdb02574 100644 GIT binary patch literal 892 zcmZuwziSjh7@c^YM$cd*22zQjkzH_h*Us`9xfBs%BMNEu?k2Y*Sa@6Fz^A`bU>kN17w&X4cA&egQgXbr zN{t??0(n@$T*bbQ`!;|kaA<Aal>-VkBl!JO^yQUU*2KdIA1v za11>9nt!KH&HOg_67cTsy%z6B-Gsje9s{r3Zj1TU4fqehyTGqTvPhqr-+2ap32ZGt zK1ZMWB>Xqvx4`y?ndkJWPr&~K{tVpzSe~IzJrDmI_$P3^nOvby&HQ;h$P#d4XY)OM zYWfNIBCvn?%USx={LTt^4Vd!!zbT`Yv#7&_#iVo{(&H&ne++L0<` zq5Dd-|L@DLwT7X8&zmVd$S}oEeMtX(m7X=WxDX}h6Mzh$+*NxzX>_jSmhSs2aOQZP s((-BishsSlxqkzM+LL&Fm#UQgWF6@sbFilKJDuBEc${PYH#oz80HtBKsQ>@~ literal 952 zcmZuvziSjh7@e4$zs_GF38WH1BYVQ^rc8O=rHG(K%n2#7mz&&!uQ%TB{DJ*OPrW0(=e?Tm))c59YS(OaDeQ)13~aKF-$~3<<=aTbv9Ef$N~|`C^}E_` zhOypO8R9U!YeRPHCZPXD1^?%P3&6z@E`ff~lkgY7 zb)Yd=eNUhII{XLVWngRW^Ho|^j~gFgW)x7Y5_ zr@jII3wQuDM?N+EAK;(B@y>3QcS~J?k0Qi9U~vDd+lQL*b?_qaYkYo&`&0A$P4F7f zKb(3=pLz;@5BwZ>^)2~MpPKRS!27`C%KSt6)I9$o_z2iYt+)wac)C_Tl#G<_L`9># z9nD83)7vJ=!&q*_I_08P&8BKSm!_*Snd!EYEn{NFyMcMIYZ@?07MB5}6;}biHG7Be zTD&>mIX6t(=IDNRgf}SC)!=zr*J`{wS!Q5JagSEUI#ESV-VgKr E0sptYHvj+t diff --git a/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml b/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml index c0b7f41..9129dc8 100644 --- a/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml +++ b/src/schemas/org.gnome.shell.extensions.visualizer.gschema.xml @@ -8,6 +8,11 @@ Location of visualizer + + '1.0,0.0,1.0,1.0' + Visualizer color + The color of the visualizer + false Flip Visualizer Vertically @@ -47,13 +52,5 @@ 720 Horizontal Size of DrawingArea - - 0 - Horizontal Position of DrawingArea - - - 0 - Vertical Position of DrawingArea - diff --git a/src/visual.js b/src/visual.js index 95de693..aafb695 100644 --- a/src/visual.js +++ b/src/visual.js @@ -25,6 +25,7 @@ var Visualizer = GObject.registerClass( this._settings.connect('changed::horizontal-flip', () => this._updateFlipSettings()); this._settings.connect('changed::visualizer-pos-x', () => this.setPosition()); this._settings.connect('changed::visualizer-pos-y', () => this.setPosition()); + this._settings.connect('changed::visualizer-color', () => this._update()); let fps = this._settings.get_int('fps'); this._visualMenuManager = new PopupMenu.PopupMenuManager(this); this._freq = []; @@ -51,7 +52,7 @@ var Visualizer = GObject.registerClass( this.startRefreshLoop(); Main.layoutManager._backgroundGroup.add_child(this); } - + startRefreshLoop() { if (this._refreshLoopId !== null) { GLib.Source.remove(this._refreshLoopId); @@ -124,22 +125,30 @@ var Visualizer = GObject.registerClass( let lineW = this._settings.get_int('spects-line-width'); let horizontal_flip = this._settings.get_boolean('horizontal-flip'); let vertical_flip = this._settings.get_boolean('flip-visualizer'); - cr.setLineWidth(lineW); - + let colorString = this._settings.get_string('visualizer-color'); + let [r, g, b, a] = colorString.split(',').map(parseFloat); + for (let i = 0; i < values; i++) { - let colorIntensity = this._freq[i] / 80; - cr.setSourceRGBA(1, colorIntensity, 1, 1); + let normalizedFreq = Math.max(Math.min(this._freq[i] / 80, 1), 0); + let intensity = Math.pow(normalizedFreq, 0.5); + intensity = Math.max(intensity, 0.2); + let blendFactor = horizontal_flip ? i / (values - 1) : 1 - i / (values - 1); + let blendedR = blendFactor * r + (1 - blendFactor); + let blendedG = blendFactor * g + (1 - blendFactor); + let blendedB = blendFactor * b + (1 - blendFactor); + cr.setSourceRGBA(blendedR * intensity, blendedG * intensity, blendedB * intensity, a); + let xPosition = horizontal_flip ? width - (lineW / 2 + i * width / values) : lineW / 2 + i * width / values; let yPosition = vertical_flip ? height / 80 * (80 - this._freq[i]) : height * this._freq[i] / 80; - + cr.moveTo(xPosition, vertical_flip ? 0 : height); cr.lineTo(xPosition, vertical_flip ? 1 : height - 1); cr.lineTo(xPosition, yPosition); cr.stroke(); } - + cr.$dispose(); } @@ -185,8 +194,7 @@ var Visualizer = GObject.registerClass( setPosition() { if (this._ignorePositionUpdate) return; - let x = this._settings.get_int('visualizer-pos-x'); - let y = this._settings.get_int('visualizer-pos-y'); + let [x, y] = this._settings.get_value('visualizer-location').deep_unpack(); this.set_position(x, y); if (!this.get_parent()) return; From 265de26b3868cd4513ae7d596b4f4e590280d6f6 Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 14:40:22 -0800 Subject: [PATCH 5/9] Remove redundant function --- src/prefs.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/prefs.js b/src/prefs.js index 5b41688..b34daba 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -23,23 +23,6 @@ function buildPrefsWidget() { return widget; } -function updatePositionMaxes() { - let visualizerWidth = this._settings.get_int('visualizer-width'); - let visualizerHeight = this._settings.get_int('visualizer-height'); - - let display = Gdk.Display.get_default(); - let monitor = display.get_primary_monitor(); - let geometry = monitor.get_geometry(); - let screenWidth = geometry.width; - let screenHeight = geometry.height; - - let maxX = screenWidth - visualizerWidth; - let maxY = screenHeight - visualizerHeight; - - this.visualizerXSpin.set_range(0, maxX); - this.visualizerYSpin.set_range(0, maxY); -} - const prefsWidget = GObject.registerClass( class prefsWidget extends Gtk.Notebook { From 4d20fc29f40190d6baa7f8863d2b3549e1909a7b Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 15:00:58 -0800 Subject: [PATCH 6/9] Cleanup code, add comment --- src/prefs.js | 79 +++++++++++++++++++++++++-------------------------- src/visual.js | 1 + 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/prefs.js b/src/prefs.js index b34daba..0950cea 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -1,13 +1,23 @@ 'use strict'; const { Gio, Gtk, Gdk, GLib, GObject } = imports.gi; -const Params = imports.misc.params; const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); +const Params = imports.misc.params; const Config = imports.misc.config; +const Me = ExtensionUtils.getCurrentExtension(); + const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); let Adw; +const DEFAULT_SPIN_MIN = 1; +const DEFAULT_SPIN_MAX = 200; +const VISUALIZER_WIDTH_MAX = 1920; +const SPECTS_LINE_WIDTH_MAX = 20; +const TOTAL_SPECTS_BAND_MAX = 256; +const FPS_OPTIONS = ["15", "30", "60", "90", "120"]; +const GRID_COLUMN_SPACING = 200; +const GRID_ROW_SPACING = 25; + function init() { } @@ -34,23 +44,25 @@ const prefsWidget = GObject.registerClass( let grid = new Gtk.Grid(); let fpsOptions = new Gtk.ComboBoxText(); - ["15", "30", "60", "90", "120"].forEach(fps => fpsOptions.append_text(fps)); + FPS_OPTIONS.forEach(fps => fpsOptions.append_text(fps)); fpsOptions.connect('changed', (widget) => { let fps = widget.get_active_text(); this._settings.set_int('fps', parseInt(fps, 10)); }); let currentFps = this._settings.get_int('fps'); fpsOptions.set_active_id(currentFps.toString()); + attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer' }), getSwitch('flip-visualizer', this._settings), 0); attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer Horizontally' }), getSwitch('horizontal-flip', this._settings), 1); - attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings), 2); - attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings), 3); - attachItems(grid, new Gtk.Label({ label: 'Spects Line Width' }), getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings), 5); - attachItems(grid, new Gtk.Label({ label: 'Change Spects Band to Get' }), getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings), 4); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', DEFAULT_SPIN_MIN, DEFAULT_SPIN_MAX, 1, this._settings), 2); + attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', DEFAULT_SPIN_MIN, VISUALIZER_WIDTH_MAX, 1, this._settings), 3); + attachItems(grid, new Gtk.Label({ label: 'Spects Line Width' }), getSpinButton(false, 'spects-line-width', DEFAULT_SPIN_MIN, SPECTS_LINE_WIDTH_MAX, 1, this._settings), 5); + attachItems(grid, new Gtk.Label({ label: 'Change Spects Band to Get' }), getSpinButton(false, 'total-spects-band', DEFAULT_SPIN_MIN, TOTAL_SPECTS_BAND_MAX, 1, this._settings), 4); attachItems(grid, new Gtk.Label({ label: 'Frames Per Second (FPS)' }), getDropDown(this._settings), 7); attachItems(grid, new Gtk.Label({ label: 'Visualizer Color' }), getColorButton(this._settings), 8); this.attachHybridRow(grid, new Gtk.Label({ label: 'Override Spect Value' }), new Gtk.Label({ label: 'Set Spects Value' }), getSwitch('spect-over-ride-bool', this._settings), getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings), 6); this.append_page(grid, new Gtk.Label({ label: 'Visualizer' })); + let aboutBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); if (major < 40) { aboutBox.add(new Gtk.Label({ label: Me.metadata.name })); @@ -77,10 +89,12 @@ class PrefsWindow { } create_page(title) { - let page = new Adw.PreferencesPage({ - title: title, - //icon_name: icon, - }); + let page = new Adw.PreferencesPage( + { + title: title, + //icon_name: icon, + } + ); this._window.add(page); // get the headerbar @@ -111,9 +125,7 @@ class PrefsWindow { } append_row(group, title, widget) { - let row = new Adw.ActionRow({ - title: title, - }); + let row = new Adw.ActionRow({ title: title }); group.add(row); row.add_suffix(widget); row.activatable_widget = widget; @@ -126,12 +138,10 @@ class PrefsWindow { expanded: this._settings.get_boolean(key), enable_expansion: this._settings.get_boolean(key) }); - let row = new Adw.ActionRow({ - title: title, - }); + + let row = new Adw.ActionRow({ title: title }); expand_row.connect("notify::enable-expansion", (widget) => { - let settingArray = this._settings.get_boolean(key); - settingArray = widget.enable_expansion; + let settingArray = widget.enable_expansion; this._settings.set_value(key, new GLib.Variant('b', settingArray)); }); row.add_suffix(key1); @@ -141,20 +151,9 @@ class PrefsWindow { append_info_group(group, name, title) { let adw_group = new Adw.PreferencesGroup(); - let infoBox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - hexpand: false, - vexpand: false - }); - - let name_label = new Gtk.Label({ - label: name, - }); - - let version = new Gtk.Label({ - label: 'Version: ' + title, - }); - + let infoBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, hexpand: false, vexpand: false}); + let name_label = new Gtk.Label({ label: name }); + let version = new Gtk.Label({ label: 'Version: ' + title }); infoBox.append(name_label); infoBox.append(version); adw_group.add(infoBox); @@ -183,8 +182,8 @@ class PrefsWindow { } function attachItems(grid, label, widget, row) { - grid.set_column_spacing(200); - grid.set_row_spacing(25); + grid.set_column_spacing(GRID_COLUMN_SPACING); + grid.set_row_spacing(GRID_ROW_SPACING); grid.attach(label, 0, row, 1, 1); grid.attach(widget, 1, row, 1, 1); } @@ -196,18 +195,16 @@ function getSwitch(key, settings) { } function getSpinButton(is_double, key, min, max, step, settings) { - let v = 0; - (is_double) ? v = settings.get_double(key) : v = settings.get_int(key); + let value = is_double ? settings.get_double(key) : settings.get_int(key); let spin = Gtk.SpinButton.new_with_range(min, max, step); - spin.set_value(v); + spin.set_value(value); settings.bind(key, spin, 'value', Gio.SettingsBindFlags.DEFAULT); return spin; } function getDropDown(settings) { let dropDown = new Gtk.ComboBoxText(); - let fpsValues = ["15", "30", "60", "90", "120"]; - fpsValues.forEach(fps => dropDown.append_text(fps)); + FPS_OPTIONS.forEach(fps => dropDown.append_text(fps)); dropDown.connect('changed', (widget) => { let fps = widget.get_active_text(); @@ -215,7 +212,7 @@ function getDropDown(settings) { }); let currentFps = settings.get_int('fps').toString(); - let currentIndex = fpsValues.indexOf(currentFps); + let currentIndex = FPS_OPTIONS.indexOf(currentFps); if (currentIndex !== -1) { dropDown.set_active(currentIndex); } diff --git a/src/visual.js b/src/visual.js index aafb695..90a5e30 100644 --- a/src/visual.js +++ b/src/visual.js @@ -138,6 +138,7 @@ var Visualizer = GObject.registerClass( let blendedG = blendFactor * g + (1 - blendFactor); let blendedB = blendFactor * b + (1 - blendFactor); cr.setSourceRGBA(blendedR * intensity, blendedG * intensity, blendedB * intensity, a); + // Todo: Adjust gradient for compatibility with horizontal flip let xPosition = horizontal_flip ? width - (lineW / 2 + i * width / values) : lineW / 2 + i * width / values; From 196b6b9a3f0dcd7c525fcb2de9f2b6cb39bdd8fd Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 18:33:44 -0800 Subject: [PATCH 7/9] Finalize edits, organize code --- src/prefs.js | 71 ++++----- src/visual.js | 405 ++++++++++++++++++++++++++++---------------------- 2 files changed, 261 insertions(+), 215 deletions(-) diff --git a/src/prefs.js b/src/prefs.js index 0950cea..f9196a2 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -6,17 +6,17 @@ const Params = imports.misc.params; const Config = imports.misc.config; const Me = ExtensionUtils.getCurrentExtension(); -const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); +const [MajorVersion, MinorVersion] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); let Adw; -const DEFAULT_SPIN_MIN = 1; -const DEFAULT_SPIN_MAX = 200; -const VISUALIZER_WIDTH_MAX = 1920; -const SPECTS_LINE_WIDTH_MAX = 20; -const TOTAL_SPECTS_BAND_MAX = 256; -const FPS_OPTIONS = ["15", "30", "60", "90", "120"]; -const GRID_COLUMN_SPACING = 200; -const GRID_ROW_SPACING = 25; +const DEFAULT_SPIN_MIN = 1; // Minimum pixel size +const DEFAULT_SPIN_MAX = 200; // Maximum pixel size +const VISUALIZER_WIDTH_MAX = 1920; // Maximum pixel size for width +const SPECTS_LINE_WIDTH_MAX = 20; // Maximum pixel size for spect line widths +const TOTAL_SPECTS_BAND_MAX = 256; // Maximum # of spect bands possible to be chosen +const FPS_OPTIONS = ["15", "30", "60", "90", "120"]; // Frame counts; going from 15 to 120 fps +const GRID_COLUMN_SPACING = 200; // Spacing between columns +const GRID_ROW_SPACING = 25; // Spacing between rows function init() { } @@ -29,30 +29,29 @@ function fillPreferencesWindow(window) { function buildPrefsWidget() { let widget = new prefsWidget(); - (major < 40) ? widget.show_all(): widget.show(); + (MajorVersion < 40) ? widget.show_all(): widget.show(); return widget; } +function attachItems(grid, label, widget, row) { + grid.set_column_spacing(GRID_COLUMN_SPACING); + grid.set_row_spacing(GRID_ROW_SPACING); + grid.attach(label, 0, row, 1, 1); + grid.attach(widget, 1, row, 1, 1); +} + const prefsWidget = GObject.registerClass( class prefsWidget extends Gtk.Notebook { _init(params) { super._init(params); + let grid = new Gtk.Grid(); this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.visualizer'); + this.setupFpsOptions(); this.margin = 20; - let grid = new Gtk.Grid(); - let fpsOptions = new Gtk.ComboBoxText(); - FPS_OPTIONS.forEach(fps => fpsOptions.append_text(fps)); - fpsOptions.connect('changed', (widget) => { - let fps = widget.get_active_text(); - this._settings.set_int('fps', parseInt(fps, 10)); - }); - let currentFps = this._settings.get_int('fps'); - fpsOptions.set_active_id(currentFps.toString()); - - attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer' }), getSwitch('flip-visualizer', this._settings), 0); + attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer Vertically' }), getSwitch('flip-visualizer', this._settings), 0); attachItems(grid, new Gtk.Label({ label: 'Flip the Visualizer Horizontally' }), getSwitch('horizontal-flip', this._settings), 1); attachItems(grid, new Gtk.Label({ label: 'Visualizer Height' }), getSpinButton(false, 'visualizer-height', DEFAULT_SPIN_MIN, DEFAULT_SPIN_MAX, 1, this._settings), 2); attachItems(grid, new Gtk.Label({ label: 'Visualizer Width' }), getSpinButton(false, 'visualizer-width', DEFAULT_SPIN_MIN, VISUALIZER_WIDTH_MAX, 1, this._settings), 3); @@ -64,7 +63,7 @@ const prefsWidget = GObject.registerClass( this.append_page(grid, new Gtk.Label({ label: 'Visualizer' })); let aboutBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); - if (major < 40) { + if (MajorVersion < 40) { aboutBox.add(new Gtk.Label({ label: Me.metadata.name })); aboutBox.add(new Gtk.Label({ label: 'Version: ' + Me.metadata.version.toString() })); } else { @@ -74,6 +73,17 @@ const prefsWidget = GObject.registerClass( this.append_page(aboutBox, new Gtk.Label({ label: 'About' })); } + setupFpsOptions() { + let fpsOptions = new Gtk.ComboBoxText(); + FPS_OPTIONS.forEach(fps => fpsOptions.append_text(fps)); + fpsOptions.connect('changed', (widget) => { + let fps = widget.get_active_text(); + this._settings.set_int('fps', parseInt(fps, 10)); + }); + let currentFps = this._settings.get_int('fps'); + fpsOptions.set_active_id(currentFps.toString()); + } + attachHybridRow(grid, label, label1, button, button1, row) { grid.attach(label, 0, row, 1, 1); grid.attach(button, 1, row, 1, 1); @@ -165,13 +175,13 @@ class PrefsWindow { let groupVisual = this.create_group(visualWidget); this.append_row(groupVisual, 'Flip the Visualizer Vertically', getSwitch('flip-visualizer', this._settings)); this.append_row(groupVisual, 'Flip the Visualizer Horizontally', getSwitch('horizontal-flip', this._settings)); - this.append_row(groupVisual, 'Visualizer Height', getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings)); - this.append_row(groupVisual, 'Visualizer Width', getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings)); - this.append_row(groupVisual, 'Spects Line Width', getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings)); - this.append_row(groupVisual, 'Change Spects Band to Get', getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings)); + this.append_row(groupVisual, 'Visualizer Height (px)', getSpinButton(false, 'visualizer-height', 1, 200, 1, this._settings)); + this.append_row(groupVisual, 'Visualizer Width (px)', getSpinButton(false, 'visualizer-width', 1, 1920, 1, this._settings)); + this.append_row(groupVisual, 'Spects Line Width (px)', getSpinButton(false, 'spects-line-width', 1, 20, 1, this._settings)); + this.append_row(groupVisual, 'Change # of Spect Bands to Get', getSpinButton(false, 'total-spects-band', 1, 256, 1, this._settings)); this.append_row(groupVisual, 'Frames Per Second (FPS)', getDropDown(this._settings)); this.append_row(groupVisual, 'Visualizer Color', getColorButton(this._settings)); - this.append_expander_row(groupVisual, 'Override Spect Value', 'Set Spects Value', 'spect-over-ride-bool', getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings)); + this.append_expander_row(groupVisual, 'Override Spect Value', 'Set Spect Value', 'spect-over-ride-bool', getSpinButton(false, 'spect-over-ride', 1, 256, 1, this._settings)); } let aboutPage = this.create_page('About'); { @@ -181,13 +191,6 @@ class PrefsWindow { } } -function attachItems(grid, label, widget, row) { - grid.set_column_spacing(GRID_COLUMN_SPACING); - grid.set_row_spacing(GRID_ROW_SPACING); - grid.attach(label, 0, row, 1, 1); - grid.attach(widget, 1, row, 1, 1); -} - function getSwitch(key, settings) { let button = new Gtk.Switch({ active: key, valign: Gtk.Align.CENTER }); settings.bind(key, button, 'active', Gio.SettingsBindFlags.DEFAULT); diff --git a/src/visual.js b/src/visual.js index 90a5e30..6bdcff7 100644 --- a/src/visual.js +++ b/src/visual.js @@ -5,10 +5,34 @@ const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PopupMenu = imports.ui.popupMenu; const Config = imports.misc.config; -const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); +const [MajorVersion, MinorVersion] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); + +// General Constants +const REFRESH_RATE_BASE = 1000; // Base ms count for calculating refresh rate +const INTERVAL_BASE = 1000000000; // Base ns count for calculating interval +const SPECTRUM_THRESHOLD = -80; // Default threshold for the spectrum +const MENU_POSITION_Y = 0.5; // Y position for popup menu +const MENU_SIDE = St.Side.TOP; // Side for popup menu +const POPUP_TIMEOUT = 600; // Timeout for popup in milliseconds + +// drawStuff Constants +const MAX_FREQUENCY = 80; // Maximum frequency value +const MIN_INTENSITY = 0.2; // Minimum intensity +const VERTICAL_FLIP_FACTOR = 80; // Factor used in calculating yPosition for vertical flip +const SQRT_VALUE = 0.5; // Square root exponent used in calculating intensity +const MAX_COLOR_VALUE = 1.0; // Maximum color value for unit rgb used in calculations +const MIN_RANGE = 0; // Minimum range value when normalizing frequency +const MAX_RANGE = 1; // Maximum range value when normalizing frequency +const MIRROR_VALUE = 1; // Mirror value used to invert factors for horizontal flipping +const MIDDLE_DIVISOR = 2; // Divisor used in calculating xPosition, used for finding the middle of the line width of lineW +const START_DRAW_Y_VALUE = 0; // Value used for drawing line segments; marks the start of the drawn line +const END_DRAW_Y_VALUE = 1; // Value used for drawing line segments; marks the end of the drawn line var Visualizer = GObject.registerClass( class musicVisualizer extends St.BoxLayout { + /* + * Initialization and Destruction Methods + */ _init() { this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.visualizer'); super._init({ @@ -18,7 +42,7 @@ var Visualizer = GObject.registerClass( }); this._settings.connect('changed::fps', () => { let fps = this._settings.get_int('fps'); - this._refreshRate = 1000 / fps; + this._refreshRate = REFRESH_RATE_BASE / fps; this.updateGstInterval(); this.startRefreshLoop(); }); @@ -47,42 +71,41 @@ var Visualizer = GObject.registerClass( this.getMenuItems(); this._update(); this.setPosition(); - this._refreshRate = 1000 / fps; + this._refreshRate = REFRESH_RATE_BASE / fps; this._refreshLoopId = null; this.startRefreshLoop(); Main.layoutManager._backgroundGroup.add_child(this); } - startRefreshLoop() { - if (this._refreshLoopId !== null) { - GLib.Source.remove(this._refreshLoopId); - } - this._refreshLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._refreshRate, () => { - this._actor.queue_repaint(); - return true; - }); + actorInit() { + this._spectBands = this._settings.get_int('total-spects-band'); + this._spectHeight = this._settings.get_int('visualizer-height'); + this._spectWidth = this._settings.get_int('visualizer-width'); + this._actor.height = this._spectHeight; + this._actor.width = this._spectWidth; } - updateGstInterval() { - let fps = this._settings.get_int('fps'); - let interval = 1000000000 / fps; - if (this._spectrum) { - this._spectrum.set_property("interval", interval); + onDestroy() { + if (this._refreshLoopId !== null) { + GLib.Source.remove(this._refreshLoopId); } + this._removeSource(this._menuTimeoutId); + this._removeSource(this._streamId); + this._removeSource(this._defaultSrcId); + this._pipeline.set_state(Gst.State.NULL); + Main.layoutManager._backgroundGroup.remove_child(this); } - _updateFlipSettings() { - this._horizontalFlip = this._settings.get_boolean('horizontal-flip'); - this._update(); - } - + /* + * GStreamer Methods + */ setupGst() { Gst.init(null); this._pipeline = Gst.Pipeline.new("bin"); this._src = Gst.ElementFactory.make("pulsesrc", "src"); this._spectrum = Gst.ElementFactory.make("spectrum", "spectrum"); this._spectrum.set_property("bands", this._spectBands); - this._spectrum.set_property("threshold", -80); + this._spectrum.set_property("threshold", SPECTRUM_THRESHOLD); this._spectrum.set_property("post-messages", true); this.updateGstInterval(); let _sink = Gst.ElementFactory.make("fakesink", "sink"); @@ -98,6 +121,14 @@ var Visualizer = GObject.registerClass( this._pipeline.set_state(Gst.State.PLAYING); } + updateGstInterval() { + let fps = this._settings.get_int('fps'); + let interval = INTERVAL_BASE / fps; + if (this._spectrum) { + this._spectrum.set_property("interval", interval); + } + } + onMessage(bus, msg) { let struct = msg.get_structure(); let [magbool, magnitudes] = struct.get_list("magnitude"); @@ -110,14 +141,62 @@ var Visualizer = GObject.registerClass( } } - actorInit() { - this._spectBands = this._settings.get_int('total-spects-band'); - this._spectHeight = this._settings.get_int('visualizer-height'); - this._spectWidth = this._settings.get_int('visualizer-width'); - this._actor.height = this._spectHeight; - this._actor.width = this._spectWidth; + /* + * Event Handlers + */ + _onDragBegin() { + this.isDragging = true; + this._dragMonitor = { + dragMotion: this._onDragMotion.bind(this) + }; + DND.addDragMonitor(this._dragMonitor); + let p = this.get_transformed_position(); + this.startX = this.oldX = p[0]; + this.startY = this.oldY = p[1]; + this.get_allocation_box(); + this.rowHeight = this.height; + this.rowWidth = this.width; + } + + _onDragEnd() { + if (this._dragMonitor) { + DND.removeDragMonitor(this._dragMonitor); + this._dragMonitor = null; + } + this.set_position(this.deltaX, this.deltaY); + this.ignoreUpdatePosition = true; + this._settings.set_value('visualizer-location', new GLib.Variant('(ii)', [this.deltaX, this.deltaY])); + this.ignoreUpdatePosition = false; + } + + _onHover() { + if (!this.hover) + this._removeMenuTimeout(); + } + + _onDragMotion(dragEvent) { + this.deltaX = dragEvent.x - (dragEvent.x - this.oldX); + this.deltaY = dragEvent.y - (dragEvent.y - this.oldY); + let p = this.get_transformed_position(); + this.oldX = p[0]; + this.oldY = p[1]; + return DND.DragMotionResult.CONTINUE; + } + + vfunc_button_press_event() { + let event = Clutter.get_current_event(); + if (event.get_button() === 1) + this._setPopupTimeout(); + else if (event.get_button() === 3) { + this._popupMenu(); + return Clutter.EVENT_STOP; + } + return Clutter.EVENT_PROPAGATE; } + /* + * Drawing and Rendering Methods + */ drawStuff(area) { let [width, height] = area.get_surface_size(); let cr = area.get_context(); @@ -125,27 +204,27 @@ var Visualizer = GObject.registerClass( let lineW = this._settings.get_int('spects-line-width'); let horizontal_flip = this._settings.get_boolean('horizontal-flip'); let vertical_flip = this._settings.get_boolean('flip-visualizer'); + let [r, g, b, a] = this._settings.get_string('visualizer-color').split(',').map(parseFloat); cr.setLineWidth(lineW); - let colorString = this._settings.get_string('visualizer-color'); - let [r, g, b, a] = colorString.split(',').map(parseFloat); for (let i = 0; i < values; i++) { - let normalizedFreq = Math.max(Math.min(this._freq[i] / 80, 1), 0); - let intensity = Math.pow(normalizedFreq, 0.5); - intensity = Math.max(intensity, 0.2); - let blendFactor = horizontal_flip ? i / (values - 1) : 1 - i / (values - 1); - let blendedR = blendFactor * r + (1 - blendFactor); - let blendedG = blendFactor * g + (1 - blendFactor); - let blendedB = blendFactor * b + (1 - blendFactor); + let normalizedFreq = Math.max(Math.min(this._freq[i] / MAX_FREQUENCY, MAX_RANGE), MIN_RANGE); + let intensity = Math.pow(normalizedFreq, SQRT_VALUE); + intensity = Math.max(intensity, MIN_INTENSITY); + + let horizontalFlip = this._settings.get_boolean('horizontal-flip'); + let positionFactor = horizontalFlip ? MIRROR_VALUE - (i / (values - MIRROR_VALUE)) : i / (values - MIRROR_VALUE); + let blendFactor = horizontalFlip ? MIRROR_VALUE - positionFactor : positionFactor; + let blendedR = r + blendFactor * (MAX_COLOR_VALUE - r); + let blendedG = g + blendFactor * (MAX_COLOR_VALUE - g); + let blendedB = b + blendFactor * (MAX_COLOR_VALUE - b); cr.setSourceRGBA(blendedR * intensity, blendedG * intensity, blendedB * intensity, a); - // Todo: Adjust gradient for compatibility with horizontal flip + let xPosition = horizontal_flip ? width - (lineW / MIDDLE_DIVISOR + i * width / values) : lineW / MIDDLE_DIVISOR + i * width / values; + let yPosition = vertical_flip ? height / VERTICAL_FLIP_FACTOR * (VERTICAL_FLIP_FACTOR - this._freq[i]) : height * this._freq[i] / MAX_FREQUENCY; - let xPosition = horizontal_flip ? width - (lineW / 2 + i * width / values) : lineW / 2 + i * width / values; - let yPosition = vertical_flip ? height / 80 * (80 - this._freq[i]) : height * this._freq[i] / 80; - - cr.moveTo(xPosition, vertical_flip ? 0 : height); - cr.lineTo(xPosition, vertical_flip ? 1 : height - 1); + cr.moveTo(xPosition, vertical_flip ? START_DRAW_Y_VALUE : height); + cr.lineTo(xPosition, vertical_flip ? END_DRAW_Y_VALUE : height - END_DRAW_Y_VALUE); cr.lineTo(xPosition, yPosition); cr.stroke(); } @@ -157,12 +236,9 @@ var Visualizer = GObject.registerClass( this._actor.queue_repaint(); } - getSpectBands() { - let override = this._settings.get_boolean('spect-over-ride-bool'); - let values = this._settings.get_int('spect-over-ride'); - return (!override) ? this._spectBands : (values <= this._spectBands) ? values : this._spectBands - } - + /* + * Utility Methods + */ _getMetaRectForCoords(x, y) { this.get_allocation_box(); let rect = new Meta.Rectangle(); @@ -176,12 +252,6 @@ var Visualizer = GObject.registerClass( return Main.layoutManager.getWorkAreaForMonitor(monitorIndex); } - _isOnScreen(x, y) { - let rect = this._getMetaRectForCoords(x, y); - let monitorWorkArea = this._getWorkAreaForRect(rect); - return monitorWorkArea.contains_rect(rect); - } - _keepOnScreen(x, y) { let rect = this._getMetaRectForCoords(x, y); let monitorWorkArea = this._getWorkAreaForRect(rect); @@ -192,6 +262,61 @@ var Visualizer = GObject.registerClass( return [x, y]; } + _removeMenuTimeout() { + if (this._menuTimeoutId > 0) { + GLib.source_remove(this._menuTimeoutId); + this._menuTimeoutId = 0; + } + } + + _setPopupTimeout() { + this._removeMenuTimeout(); + this._menuTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, POPUP_TIMEOUT, () => { + this._menuTimeoutId = 0; + this._popupMenu(); + return GLib.SOURCE_REMOVE; + }); + GLib.Source.set_name_by_id(this._menuTimeoutId, '[visualizer] this.popupMenu'); + } + + /* + * Getters, Setters + */ + getStreams() { + return new Promise((resolve, reject) => { + this._streamId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => { + let control = (MajorVersion < 43) ? Main.panel.statusArea.aggregateMenu._volume._control : Main.panel.statusArea.quickSettings._volume._control; + if (control.get_state() == Gvc.MixerControlState.READY) { + let streams = control.get_streams(); + (streams.length > 0) ? resolve(streams): reject(Error('failure')) + } + return GLib.SOURCE_REMOVE; + }); + }); + } + + getDefaultSrc() { + return new Promise((resolve, reject) => { + this._defaultSrcId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => { + let stream = (MajorVersion < 43) ? Main.panel.statusArea.aggregateMenu._volume._volumeMenu._output.stream : Main.panel.statusArea.quickSettings._volume._output.stream; + (stream !== null) ? resolve(stream.get_name() + '.monitor'): reject(Error('failure')); + return GLib.SOURCE_REMOVE; + }); + }); + } + + getSpectBands() { + let override = this._settings.get_boolean('spect-over-ride-bool'); + let values = this._settings.get_int('spect-over-ride'); + return (!override) ? this._spectBands : (values <= this._spectBands) ? values : this._spectBands + } + + getDragActor() {} + + getDragActorSource() { + return this; + } + setPosition() { if (this._ignorePositionUpdate) return; @@ -213,46 +338,49 @@ var Visualizer = GObject.registerClass( } } - _onDragBegin() { - this.isDragging = true; - this._dragMonitor = { - dragMotion: this._onDragMotion.bind(this) - }; - DND.addDragMonitor(this._dragMonitor); - let p = this.get_transformed_position(); - this.startX = this.oldX = p[0]; - this.startY = this.oldY = p[1]; - this.get_allocation_box(); - this.rowHeight = this.height; - this.rowWidth = this.width; + /* + * Lifecycle-related Methods + */ + startRefreshLoop() { + if (this._refreshLoopId !== null) { + GLib.Source.remove(this._refreshLoopId); + } + this._refreshLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._refreshRate, () => { + this._actor.queue_repaint(); + return true; + }); } - _onDragMotion(dragEvent) { - this.deltaX = dragEvent.x - (dragEvent.x - this.oldX); - this.deltaY = dragEvent.y - (dragEvent.y - this.oldY); - let p = this.get_transformed_position(); - this.oldX = p[0]; - this.oldY = p[1]; - return DND.DragMotionResult.CONTINUE; + settingsChanged() { + this._settings.connect('changed::visualizer-location', () => this.setPosition()); + this._settings.connect('changed::total-spects-band', () => { + this.actorInit(); + this._spectrum.set_property("bands", this._spectBands); + this._update(); + }); + this._settings.connect('changed::visualizer-height', () => { + this.actorInit(); + this._update(); + }); + this._settings.connect('changed::visualizer-width', () => { + this.actorInit(); + this._update(); + }); + this._settings.connect('changed::spect-over-ride', () => this.getSpectBands()); + this._settings.connect('changed::spect-over-ride-bool', () => this.getSpectBands()); + this._settings.connect('changed::spects-line-width', () => this._update()); } - _onDragEnd() { - if (this._dragMonitor) { - DND.removeDragMonitor(this._dragMonitor); - this._dragMonitor = null; + _removeSource(src) { + if (src) { + GLib.Source.remove(src); + src = null; } - this.set_position(this.deltaX, this.deltaY); - this.ignoreUpdatePosition = true; - this._settings.set_value('visualizer-location', new GLib.Variant('(ii)', [this.deltaX, this.deltaY])); - this.ignoreUpdatePosition = false; - } - - getDragActor() {} - - getDragActorSource() { - return this; } + /* + * Async Methods + */ async getMenuItems() { try { this._menuItems = []; @@ -284,67 +412,14 @@ var Visualizer = GObject.registerClass( } } - getDefaultSrc() { - return new Promise((resolve, reject) => { - this._defaultSrcId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => { - let stream = (major < 43) ? Main.panel.statusArea.aggregateMenu._volume._volumeMenu._output.stream : Main.panel.statusArea.quickSettings._volume._output.stream; - (stream !== null) ? resolve(stream.get_name() + '.monitor'): reject(Error('failure')); - return GLib.SOURCE_REMOVE; - }); - }); - } - - getStreams() { - return new Promise((resolve, reject) => { - this._streamId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => { - let control = (major < 43) ? Main.panel.statusArea.aggregateMenu._volume._control : Main.panel.statusArea.quickSettings._volume._control; - if (control.get_state() == Gvc.MixerControlState.READY) { - let streams = control.get_streams(); - (streams.length > 0) ? resolve(streams): reject(Error('failure')) - } - return GLib.SOURCE_REMOVE; - }); - }); - } - - vfunc_button_press_event() { - let event = Clutter.get_current_event(); - if (event.get_button() === 1) - this._setPopupTimeout(); - else if (event.get_button() === 3) { - this._popupMenu(); - return Clutter.EVENT_STOP; - } - return Clutter.EVENT_PROPAGATE; - } - - _onHover() { - if (!this.hover) - this._removeMenuTimeout(); - } - - _removeMenuTimeout() { - if (this._menuTimeoutId > 0) { - GLib.source_remove(this._menuTimeoutId); - this._menuTimeoutId = 0; - } - } - - _setPopupTimeout() { - this._removeMenuTimeout(); - this._menuTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 600, () => { - this._menuTimeoutId = 0; - this._popupMenu(); - return GLib.SOURCE_REMOVE; - }); - GLib.Source.set_name_by_id(this._menuTimeoutId, '[visualizer] this.popupMenu'); - } - + /* + * Miscellaneous Methods + */ _popupMenu() { this._removeMenuTimeout(); if (!this._menu) { this._subMenuItem = []; - this._menu = new PopupMenu.PopupMenu(this, 0.5, St.Side.TOP); + this._menu = new PopupMenu.PopupMenu(this, MENU_POSITION_Y, MENU_SIDE); let srcDevice = new PopupMenu.PopupSubMenuMenuItem('Change Audio Source'); this._menu.addMenuItem(srcDevice); for (let i = 0; i < this._menuItems.length; i++) { @@ -372,41 +447,9 @@ var Visualizer = GObject.registerClass( return false; } - onDestroy() { - if (this._refreshLoopId !== null) { - GLib.Source.remove(this._refreshLoopId); - } - this._removeSource(this._menuTimeoutId); - this._removeSource(this._streamId); - this._removeSource(this._defaultSrcId); - this._pipeline.set_state(Gst.State.NULL); - Main.layoutManager._backgroundGroup.remove_child(this); - } - - settingsChanged() { - this._settings.connect('changed::visualizer-location', () => this.setPosition()); - this._settings.connect('changed::total-spects-band', () => { - this.actorInit(); - this._spectrum.set_property("bands", this._spectBands); - this._update(); - }); - this._settings.connect('changed::visualizer-height', () => { - this.actorInit(); - this._update(); - }); - this._settings.connect('changed::visualizer-width', () => { - this.actorInit(); - this._update(); - }); - this._settings.connect('changed::spect-over-ride', () => this.getSpectBands()); - this._settings.connect('changed::spect-over-ride-bool', () => this.getSpectBands()); - this._settings.connect('changed::spects-line-width', () => this._update()); - } - - _removeSource(src) { - if (src) { - GLib.Source.remove(src); - src = null; - } + _isOnScreen(x, y) { + let rect = this._getMetaRectForCoords(x, y); + let monitorWorkArea = this._getWorkAreaForRect(rect); + return monitorWorkArea.contains_rect(rect); } }); From 8da5e28fe921175fa92b0f638288440a1d3afca6 Mon Sep 17 00:00:00 2001 From: Vitaly Vakhteev Date: Sat, 30 Dec 2023 18:55:02 -0800 Subject: [PATCH 8/9] Delete .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 723ef36..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea \ No newline at end of file From 30ff2dd28a6592e4636946b5f913515502a3279f Mon Sep 17 00:00:00 2001 From: VitalyVakhteev Date: Sat, 30 Dec 2023 19:23:31 -0800 Subject: [PATCH 9/9] Organize settings --- src/visual.js | 78 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/src/visual.js b/src/visual.js index 6bdcff7..30ff45a 100644 --- a/src/visual.js +++ b/src/visual.js @@ -40,43 +40,46 @@ var Visualizer = GObject.registerClass( track_hover: true, can_focus: true }); - this._settings.connect('changed::fps', () => { - let fps = this._settings.get_int('fps'); - this._refreshRate = REFRESH_RATE_BASE / fps; - this.updateGstInterval(); - this.startRefreshLoop(); - }); - this._settings.connect('changed::horizontal-flip', () => this._updateFlipSettings()); - this._settings.connect('changed::visualizer-pos-x', () => this.setPosition()); - this._settings.connect('changed::visualizer-pos-y', () => this.setPosition()); - this._settings.connect('changed::visualizer-color', () => this._update()); - let fps = this._settings.get_int('fps'); + this._initializeSettings(); this._visualMenuManager = new PopupMenu.PopupMenuManager(this); this._freq = []; this._actor = new St.DrawingArea(); this.add_child(this._actor); this.settingsChanged(); - this._draggable = DND.makeDraggable(this); - this._draggable._animateDragEnd = (eventTime) => { - this._draggable._animationInProgress = true; - this._draggable._onAnimationComplete(this._draggable._dragActor, eventTime); - }; - this._draggable.connect('drag-begin', this._onDragBegin.bind(this)); - this._draggable.connect('drag-end', this._onDragEnd.bind(this)); - this.connect('notify::hover', () => this._onHover()); - this.actorInit(); - this._actor.connect('repaint', (area) => this.drawStuff(area)); + this.setupDraggable(); + this.setupActor(); this.setupGst(); this.setDefaultSrc(); this.getMenuItems(); this._update(); this.setPosition(); - this._refreshRate = REFRESH_RATE_BASE / fps; this._refreshLoopId = null; this.startRefreshLoop(); Main.layoutManager._backgroundGroup.add_child(this); } + setupDraggable() { + this._draggable = DND.makeDraggable(this); + this._draggable._animateDragEnd = (eventTime) => { + this._draggable._animationInProgress = true; + this._draggable._onAnimationComplete(this._draggable._dragActor, eventTime); + }; + + this._draggable.connect('drag-begin', this._onDragBegin.bind(this)); + this._draggable.connect('drag-end', this._onDragEnd.bind(this)); + + this.connect('notify::hover', () => this._onHover()); + + this.isDragging = false; + this._dragMonitor = null; + this.startX = 0; + this.startY = 0; + this.oldX = 0; + this.oldY = 0; + this.deltaX = 0; + this.deltaY = 0; + } + actorInit() { this._spectBands = this._settings.get_int('total-spects-band'); this._spectHeight = this._settings.get_int('visualizer-height'); @@ -85,6 +88,21 @@ var Visualizer = GObject.registerClass( this._actor.width = this._spectWidth; } + setupActor() { + this.actorInit(); + this._actor.connect('repaint', (area) => this.drawStuff(area)); + } + + _initializeSettings() { + this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.visualizer'); + this._connectSetting('fps', this._updateRefreshRate.bind(this)); + this._connectSetting('horizontal-flip', this._updateFlipSettings.bind(this)); + this._connectSetting('visualizer-pos-x', this.setPosition.bind(this)); + this._connectSetting('visualizer-pos-y', this.setPosition.bind(this)); + this._connectSetting('visualizer-color', this._update.bind(this)); + this._refreshRate = REFRESH_RATE_BASE / this._settings.get_int('fps'); + } + onDestroy() { if (this._refreshLoopId !== null) { GLib.Source.remove(this._refreshLoopId); @@ -236,6 +254,11 @@ var Visualizer = GObject.registerClass( this._actor.queue_repaint(); } + _updateFlipSettings() { + this._horizontalFlip = this._settings.get_boolean('horizontal-flip'); + this._update(); + } + /* * Utility Methods */ @@ -279,6 +302,17 @@ var Visualizer = GObject.registerClass( GLib.Source.set_name_by_id(this._menuTimeoutId, '[visualizer] this.popupMenu'); } + _connectSetting(key, callback) { + this._settings.connect(`changed::${key}`, callback); + } + + _updateRefreshRate() { + let fps = this._settings.get_int('fps'); + this._refreshRate = REFRESH_RATE_BASE / fps; + this.updateGstInterval(); + this.startRefreshLoop(); + } + /* * Getters, Setters */