[gnome-sound-recorder] Redesign the waveform



commit e15efe621dc6ec1afc4a2acad56396eb722ea160
Author: Kavan Mevada <kavanmevada gmail com>
Date:   Mon Jun 15 17:32:52 2020 +0530

    Redesign the waveform

 src/recorder.js |  65 ++++++++++++-------------------
 src/waveform.js | 116 ++++++++++++++++++++++++++------------------------------
 src/window.js   |   6 +--
 3 files changed, 80 insertions(+), 107 deletions(-)
---
diff --git a/src/recorder.js b/src/recorder.js
index 6d9f329..31468bc 100644
--- a/src/recorder.js
+++ b/src/recorder.js
@@ -62,9 +62,11 @@ var Recorder = new GObject.registerClass({
             'Recording Duration', 'Recording duration in seconds',
             GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
             0, GLib.MAXINT16, 0),
-    },
-    Signals: {
-        'waveform': { param_types: [GObject.TYPE_INT, GObject.TYPE_FLOAT] },
+        'current-peak': GObject.ParamSpec.float(
+            'current-peak',
+            'Waveform current peak', 'Waveform current peak in float [0, 1]',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+            0.0, 1.0, 0.0),
     },
 }, class Recorder extends GObject.Object {
     _init() {
@@ -93,15 +95,11 @@ var Recorder = new GObject.registerClass({
             log(`Not all elements could be addded.\n${error}`);
         }
 
-        this.clock = this.pipeline.get_clock();
-
         srcElement.link(audioConvert);
         audioConvert.link_filtered(this.level, caps);
     }
 
     start() {
-        this.baseTime = 0;
-
         let index = 1;
         do {
             /* Translators: ""Recording %d"" is the default name assigned to a file created
@@ -112,7 +110,7 @@ var Recorder = new GObject.registerClass({
 
         this.recordBus = this.pipeline.get_bus();
         this.recordBus.add_signal_watch();
-        this.recordBus.connect('message', (recordBus, message) => {
+        this.handlerId = this.recordBus.connect('message', (_, message) => {
             if (message !== null)
                 this._onMessageReceived(message);
         });
@@ -152,6 +150,7 @@ var Recorder = new GObject.registerClass({
 
         if (this.recordBus) {
             this.recordBus.remove_watch();
+            this.recordBus.disconnect(this.handlerId);
             this.recordBus = null;
         }
 
@@ -170,39 +169,11 @@ var Recorder = new GObject.registerClass({
             }
 
             let s = message.get_structure();
-            if (s) {
-                if (s.has_name('level')) {
-                    let peakVal = 0;
-                    peakVal = s.get_value('peak');
-
-                    if (peakVal) {
-                        let val = peakVal.get_nth(0);
-
-                        if (val > 0)
-                            val = 0;
-
-                        const peak = Math.pow(10, val / 20);
-
-
-                        if  (this.clock === null)
-                            this.clock = this.pipeline.get_clock();
+            if (s && s.has_name('level')) {
+                const peakVal = s.get_value('peak');
 
-                        let absoluteTime;
-                        try {
-                            absoluteTime = this.clock.get_time();
-                        } catch (error) {
-                            absoluteTime = 0;
-                        }
-
-
-                        if (this.baseTime === 0)
-                            this.baseTime = absoluteTime;
-
-                        const runTime = absoluteTime - this.baseTime;
-                        let approxTime = Math.round(runTime / 100000000);
-                        this.emit('waveform', approxTime, peak);
-                    }
-                }
+                if (peakVal)
+                    this.current_peak = peakVal.get_nth(0);
             }
             break;
         }
@@ -243,6 +214,20 @@ var Recorder = new GObject.registerClass({
         return this._duration;
     }
 
+    // eslint-disable-next-line camelcase
+    get current_peak() {
+        return this._current_peak;
+    }
+
+    // eslint-disable-next-line camelcase
+    set current_peak(peak) {
+        if (peak > 0)
+            peak = 0;
+
+        this._current_peak = Math.pow(10, peak / 20);
+        this.notify('current-peak');
+    }
+
     set duration(val) {
         this._duration = val;
         this.notify('duration');
diff --git a/src/waveform.js b/src/waveform.js
index 54fa8eb..869f21e 100644
--- a/src/waveform.js
+++ b/src/waveform.js
@@ -1,99 +1,89 @@
-/* exported WaveForm */
+
+/* exported WaveForm
 /*
-* Copyright 2013 Meg Ford
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Library General Public
-* License as published by the Free Software Foundation; either
-* version 2 of the License, or (at your option) any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Library General Public License for more details.
-*
-* You should have received a copy of the GNU Library General Public
-* License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*
-*
-* Author: Meg Ford <megford gnome org>
-*/
+ * Copyright 2013 Meg Ford
+             2020 Kavan Mevada
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Author: Meg Ford <megford gnome org>
+ *          Kavan Mevada <kavanmevada gmail com>
+ *
+ */
 
 // based on code from Pitivi
 
 const { GObject, Gtk } = imports.gi;
 const Cairo = imports.cairo;
 
-const WAVE_SAMPLES = 40;
+const GUTTER = 4;
 
 var WaveForm = GObject.registerClass({
-    GTypeName: 'WaveForm',
+    Properties: {
+        'peak': GObject.ParamSpec.float(
+            'peak',
+            'Waveform current peak', 'Waveform current peak in float [0, 1]',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+            0.0, 1.0, 0.0),
+    },
 }, class WaveForm extends Gtk.DrawingArea {
-
     _init() {
+        this.peaks = [];
         super._init({
             vexpand: true,
             valign: Gtk.Align.FILL,
         });
-        this.peaks = [];
         this.show();
     }
 
-    vfunc_draw(cr) {
-        let xAxis = 0;
-        let start = this.recordedTime;
-        let end = start + WAVE_SAMPLES;
-        let width = this.get_allocated_width();
-        let height = this.get_allocated_height();
-        let pixelsPerSample = width / WAVE_SAMPLES;
-        let gradient = new Cairo.LinearGradient(0, 0, width, height);
-
-        gradient.addColorStopRGBA(0.75, 0.0, 0.72, 0.64, 0.35);
-        gradient.addColorStopRGBA(0.0, 0.2, 0.54, 0.47, 0.22);
-        cr.setLineWidth(1);
-        cr.setSourceRGBA(0.0, 185, 161, 255);
+    vfunc_draw(ctx) {
+        const maxHeight = this.get_allocated_height();
+        const vertiCenter = maxHeight / 2;
+        const horizCenter = this.get_allocated_width() / 2;
 
-        for (let i = start; i <= end; i++) {
+        let pointer = horizCenter;
 
-            // Keep moving until we get to a non-null array member
-            if (this.peaks[i] && this.peaks[i] < 0)
-                cr.moveTo(xAxis * pixelsPerSample, height - this.peaks[i] * height);
+        ctx.setLineCap(Cairo.LineCap.ROUND);
+        ctx.setLineWidth(2);
+        ctx.setSourceRGBA(255, 0, 0, 1);
 
+        ctx.moveTo(horizCenter, vertiCenter - maxHeight);
+        ctx.lineTo(horizCenter, vertiCenter + maxHeight);
+        ctx.stroke();
 
-            // Start drawing when we reach the first non-null array member
-            if (this.peaks[i] && this.peaks[i] >= 0) {
+        ctx.setLineWidth(1);
+        ctx.setSourceRGBA(0, 0, 0, 1);
+        for (let index = this.peaks.length; index > 0; index--) {
+            const peak = this.peaks[index];
 
-                if (start >= WAVE_SAMPLES && xAxis === 0)
-                    cr.moveTo(xAxis * pixelsPerSample, height);
+            ctx.moveTo(pointer, vertiCenter + peak * maxHeight);
+            ctx.lineTo(pointer, vertiCenter - peak * maxHeight);
+            ctx.stroke();
 
-                cr.lineTo(xAxis * pixelsPerSample, height - this.peaks[i] * height);
-            }
-
-            xAxis += 1;
+            pointer -= GUTTER;
         }
-
-
-        cr.lineTo(xAxis * pixelsPerSample, height);
-        cr.closePath();
-        cr.strokePreserve();
-        cr.setSource(gradient);
-        cr.fillPreserve();
-        cr.$dispose();
     }
 
-    drawAt(time, peak) {
-        // Reset on Time = 0
-        if (time === 0)
-            this.peaks = Array(WAVE_SAMPLES).fill(-this.get_allocated_height());
+    set peak(p) {
+        if (this.peaks.length > this.get_allocated_width() / (2 * GUTTER))
+            this.peaks.shift();
 
-        this.peaks.push(peak);
-        this.recordedTime = time;
+        this.peaks.push(p.toFixed(2));
         this.queue_draw();
     }
 
     destroy() {
-        this.recordedTime = 0;
         this.peaks.length = 0;
         this.queue_draw();
     }
-
 });
diff --git a/src/window.js b/src/window.js
index e495799..6d3f72d 100644
--- a/src/window.js
+++ b/src/window.js
@@ -17,6 +17,7 @@
 * Author: Meg Ford <megford gnome org>
 *
 */
+
 const { GObject, Handy } = imports.gi;
 
 const { Player } = imports.player;
@@ -42,10 +43,7 @@ var Window = GObject.registerClass({
         this.waveform = new WaveForm();
         this._recorderBox.add(this.waveform);
 
-        this.recorder.connect('waveform', (_, time, peak) => {
-            this.waveform.drawAt(time, peak);
-        });
-
+        this.recorder.bind_property('current-peak', this.waveform, 'peak', GObject.BindingFlags.SYNC_CREATE 
| GObject.BindingFlags.DEFAULT);
         this.recorder.connect('notify::duration', _recorder => {
             this._recorderTime.label = formatTime(_recorder.duration);
         });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]