[gnome-sound-recorder/bilelmoussaoui/wave] generate waveform for old recordings




commit 566e7d5259770a6c75f72d4744b8af97cfa3712f
Author: Bilal Elmoussaoui <bil elmoussaoui gmail com>
Date:   Sun Aug 9 15:33:36 2020 +0200

    generate waveform for old recordings

 data/ui/row.ui     | 48 +++++++++++++++++++++++++++++++++++++-----------
 src/application.js |  3 +--
 src/recording.js   | 44 +++++++++++++++++++++++++++++++++++++++++++-
 src/row.js         | 11 +++++++----
 4 files changed, 88 insertions(+), 18 deletions(-)
---
diff --git a/data/ui/row.ui b/data/ui/row.ui
index c87720d9..ba0919e9 100644
--- a/data/ui/row.ui
+++ b/data/ui/row.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.2 -->
+<!-- Generated with glade 3.36.0 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
   <requires lib="libhandy" version="0.0"/>
@@ -132,6 +132,28 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkStack" id="waveformStack">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="transition_type">crossfade</property>
+                    <child>
+                      <object class="GtkSpinner">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="active">True</property>
+                      </object>
+                      <packing>
+                        <property name="name">loading</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
                 <child>
                   <object class="GtkBox">
                     <property name="visible">True</property>
@@ -296,6 +318,11 @@
                               <class name="pill-button"/>
                             </style>
                           </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
                         </child>
                       </object>
                       <packing>
@@ -464,21 +491,20 @@
   </template>
   <menu id="optionMenu">
     <section>
-    <item>
+      <item>
         <attribute name="action">recording.rename</attribute>
         <attribute name="label" translatable="yes">Rename</attribute>
-    </item>
-    <item>
+      </item>
+      <item>
         <attribute name="action">recording.export</attribute>
         <attribute name="label" translatable="yes">Export</attribute>
-    </item>
+      </item>
     </section>
   </menu>
   <object class="GtkSizeGroup">
-  <property name="mode">GTK_SIZE_GROUP_HORIZONTAL</property>
-  <widgets>
-    <widget name="rightStack"/>
-    <widget name="deleteBtnBox"/>
-  </widgets>
-</object>
+    <widgets>
+      <widget name="rightStack"/>
+      <widget name="deleteBtnBox"/>
+    </widgets>
+  </object>
 </interface>
diff --git a/src/application.js b/src/application.js
index 22a27da2..ecac2c12 100644
--- a/src/application.js
+++ b/src/application.js
@@ -20,8 +20,7 @@
 
 const { Gdk, Gio, GLib, GObject, Gst, Gtk, Handy } = imports.gi;
 
-/* Translators: "Recordings" here refers to the name of the directory where the application places files */
-var RecordingsDir = Gio.file_new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), pkg.name]));
+var RecordingsDir = Gio.file_new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), pkg.name]))
 var CacheDir = Gio.file_new_for_path(GLib.build_filenamev([GLib.get_user_cache_dir(), pkg.name]));
 var Settings = new Gio.Settings({ schema: pkg.name });
 
diff --git a/src/recording.js b/src/recording.js
index 8b5dbd24..e5b8d6f6 100644
--- a/src/recording.js
+++ b/src/recording.js
@@ -1,11 +1,12 @@
 /* exported Recording */
-const { Gio, GLib, GObject, GstPbutils } = imports.gi;
+const { Gio, GLib, GObject, Gst, GstPbutils } = imports.gi;
 const { CacheDir } = imports.application;
 const ByteArray = imports.byteArray;
 
 var Recording = new GObject.registerClass({
     Signals: {
         'peaks-updated': {},
+        'peaks-loading': {},
     },
     Properties: {
         'duration': GObject.ParamSpec.int(
@@ -23,6 +24,7 @@ var Recording = new GObject.registerClass({
     _init(file) {
         this._file = file;
         this._peaks = [];
+        this._loadedPeaks = [];
         super._init({});
 
         let info = file.query_info('time::created,time::modified', 0, null);
@@ -123,7 +125,47 @@ var Recording = new GObject.registerClass({
                     log(`Error reading waveform data file: ${this.name}_data`);
                 }
             });
+        } else {
+            this.emit('peaks-loading');
+            this.generatePeaks();
         }
     }
 
+    generatePeaks() {
+        const pipeline = Gst.parse_launch(`uridecodebin name=uridecodebin ! audioconvert ! 
audio/x-raw,channels=1 ! level name=level ! fakesink name=faked`);
+
+        let uridecodebin = pipeline.get_by_name("uridecodebin");
+        uridecodebin.set_property("uri", this.uri);
+
+        let fakesink = pipeline.get_by_name('faked');
+        fakesink.set_property("qos", false);
+        fakesink.set_property("sync", true);
+
+        const bus = pipeline.get_bus();
+        pipeline.set_state(Gst.State.PLAYING);
+        bus.add_signal_watch();
+
+        bus.connect("message", (bus, message) => {
+            switch (message.type) {
+                case Gst.MessageType.ELEMENT:
+                    let s = message.get_structure();
+                    if (s && s.has_name('level')) {
+                        const peakVal = s.get_value('peak');
+
+                        if (peakVal) {
+                            const peak = peakVal.get_nth(0);
+                            this._loadedPeaks.push(Math.pow(10, peak / 20));
+                        }
+                    }
+                    break;
+                case Gst.MessageType.EOS:
+                    this.peaks = this._loadedPeaks;
+                    pipeline.set_state(Gst.State.NULL);
+                    break;
+            }
+        });
+    }
 });
+
+
+
diff --git a/src/row.js b/src/row.js
index 28f96fff..8e281182 100644
--- a/src/row.js
+++ b/src/row.js
@@ -10,7 +10,7 @@ var RowState = {
 
 var Row = GObject.registerClass({
     Template: 'resource:///org/gnome/SoundRecorder/ui/row.ui',
-    InternalChildren: ['playbackStack', 'mainStack', 'playButton', 'pauseButton', 'name', 'entry', 'date', 
'duration', 'revealer', 'playbackControls', 'rightStack', 'squeezer', 'saveBtn', 'renameBtn', 'exportBtn', 
'saveBtn', 'rightStack', 'optionBox', 'seekBackward', 'seekForward', 'optionBtn', 'deleteBtn'],
+    InternalChildren: ['playbackStack', 'mainStack', 'playButton', 'waveformStack', 'pauseButton', 'name', 
'entry', 'date', 'duration', 'revealer', 'playbackControls', 'rightStack', 'squeezer', 'saveBtn', 
'renameBtn', 'exportBtn', 'saveBtn', 'rightStack', 'seekBackward', 'seekForward', 'optionBtn', 'deleteBtn'],
     Signals: {
         'play': { param_types: [GObject.TYPE_STRING] },
         'pause': {},
@@ -39,9 +39,7 @@ var Row = GObject.registerClass({
             margin_left: 12,
             margin_right: 12,
         }, WaveType.PLAYER);
-
-        this._optionBox.add(this.waveform);
-        this._optionBox.reorder_child(this.waveform, 0);
+        this._waveformStack.add_named(this.waveform, 'wave');
 
         recording.bind_property('name', this._name, 'label', GObject.BindingFlags.SYNC_CREATE | 
GObject.BindingFlags.DEFAULT);
         recording.bind_property('name', this._entry, 'text', GObject.BindingFlags.SYNC_CREATE | 
GObject.BindingFlags.DEFAULT);
@@ -92,9 +90,14 @@ var Row = GObject.registerClass({
 
         this.waveform.peaks = this._recording.peaks;
         this._recording.connect('peaks-updated', _ => {
+            this._waveformStack.visible_child_name = 'wave';
             this.waveform.peaks = this._recording.peaks;
         });
 
+        this._recording.connect('peaks-loading', _ => {
+            this._waveformStack.visible_child_name = 'loading';
+        });
+
         recording.connect('notify::duration', () => {
             this._duration.label = formatTime(recording.duration / Gst.SECOND);
         });


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