[gnome-sound-recorder/bilelmoussaoui/wave] generate waveform for old recordings
- From: Bilal Elmoussaoui <bilelmoussaoui src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-sound-recorder/bilelmoussaoui/wave] generate waveform for old recordings
- Date: Sun, 9 Aug 2020 14:11:19 +0000 (UTC)
commit b7ce8ee4d06de7b6f282c6073993c74acb4d0376
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 | 1 -
src/recording.js | 42 +++++++++++++++++++++++++++++++++++++++++-
src/row.js | 11 +++++++----
4 files changed, 85 insertions(+), 17 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..79777618 100644
--- a/src/application.js
+++ b/src/application.js
@@ -20,7 +20,6 @@
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 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..cb82700b 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,45 @@ 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:
+ const 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]