[gnome-sound-recorder] listrow: migrate to use glade Part of #65



commit 79beccc4cddf04e44f9dff0fa95e0c3c349d1c34
Author: Kavan Mevada <kavanmevada gmail com>
Date:   Wed Apr 1 02:15:50 2020 +0530

    listrow: migrate to use glade
    Part of #65

 data/org.gnome.SoundRecorder.data.gresource.xml  |   1 +
 data/ui/row.ui                                   | 177 +++++++++
 po/POTFILES.in                                   |   4 +-
 src/listview.js                                  |   5 +-
 src/mainWindow.js                                | 457 ++---------------------
 src/org.gnome.SoundRecorder.src.gresource.xml.in |   3 +-
 src/{play.js => player.js}                       |  83 ++--
 src/preferences.js                               |   9 +-
 src/record.js                                    |  24 +-
 src/row.js                                       |  56 +++
 src/utils.js                                     |  24 ++
 11 files changed, 339 insertions(+), 504 deletions(-)
---
diff --git a/data/org.gnome.SoundRecorder.data.gresource.xml b/data/org.gnome.SoundRecorder.data.gresource.xml
index 6700b5d..16a2d37 100644
--- a/data/org.gnome.SoundRecorder.data.gresource.xml
+++ b/data/org.gnome.SoundRecorder.data.gresource.xml
@@ -5,6 +5,7 @@
     <file>ui/window.ui</file>
     <file>ui/preferences.ui</file>
     <file>ui/infodialog.ui</file>
+    <file>ui/row.ui</file>
   </gresource>
 </gresources>
 
diff --git a/data/ui/row.ui b/data/ui/row.ui
new file mode 100644
index 0000000..b7a356c
--- /dev/null
+++ b/data/ui/row.ui
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <template class="Gjs_Row" parent="GtkListBoxRow">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="activatable">False</property>
+    <property name="selectable">False</property>
+    <child>
+      <object class="GtkBox">
+        <property name="height_request">45</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin">8</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <child>
+          <object class="GtkStack" id="playbackStack">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButton" id="playButton">
+                <property name="name">playButton</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="halign">center</property>
+                <property name="valign">center</property>
+                <property name="vexpand">True</property>
+                <property name="always_show_image">True</property>
+                <child>
+                  <object class="GtkImage" id="playIcon">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="icon_name">media-playback-start-symbolic</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">play</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="pauseButton">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="halign">center</property>
+                <property name="valign">center</property>
+                <property name="vexpand">True</property>
+                <property name="always_show_image">True</property>
+                <child>
+                  <object class="GtkImage" id="pauseIcon">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="icon_name">media-playback-pause-symbolic</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">pause</property>
+                <property name="position">1</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>
+            <property name="can_focus">False</property>
+            <property name="valign">center</property>
+            <property name="margin_start">8</property>
+            <property name="margin_end">8</property>
+            <property name="hexpand">True</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkLabel" id="fileNameLabel">
+                <property name="name">FileNameLabel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="valign">center</property>
+                <property name="hexpand">True</property>
+                <property name="ellipsize">end</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="fileDurationLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="valign">center</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="deleteButton">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="tooltip_text" translatable="yes">Delete</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="margin_start">4</property>
+            <property name="margin_end">4</property>
+            <property name="vexpand">True</property>
+            <property name="always_show_image">True</property>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">user-trash-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="infoButton">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="tooltip_text" translatable="yes">Details</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="margin_start">4</property>
+            <property name="margin_end">4</property>
+            <property name="vexpand">True</property>
+            <property name="always_show_image">True</property>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">dialog-information-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 14f39a4..0ebedb3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,14 +4,16 @@ data/org.gnome.SoundRecorder.desktop.in.in
 data/ui/window.ui
 data/ui/preferences.ui
 data/ui/infodialog.ui
+data/ui/row.ui
 src/audioProfile.js
 src/application.js
 src/utils.js
 src/info.js
 src/listview.js
+src/row.js
 src/main.js
 src/mainWindow.js
-src/play.js
+src/player.js
 src/preferences.js
 src/record.js
 src/waveform.js
diff --git a/src/listview.js b/src/listview.js
index f12c61e..90c980e 100644
--- a/src/listview.js
+++ b/src/listview.js
@@ -26,6 +26,7 @@ const GstPbutils = imports.gi.GstPbutils;
 
 const AudioProfile = imports.audioProfile;
 const MainWindow = imports.mainWindow;
+const Record = imports.record;
 
 const EnumeratorState = {
     ACTIVE: 0,
@@ -256,7 +257,7 @@ var Listview = class Listview {
         }
         if (eventType === Gio.FileMonitorEvent.MOVED_OUT ||
             eventType === Gio.FileMonitorEvent.CHANGES_DONE_HINT &&
-                MainWindow.recordPipeline === MainWindow.RecordPipelineStates.STOPPED || eventType === 
Gio.FileMonitorEvent.RENAMED) {
+                Record.pipeState === Record.PipelineStates.STOPPED || eventType === 
Gio.FileMonitorEvent.RENAMED) {
             stopVal = EnumeratorState.ACTIVE;
             allFilesInfo.length = 0;
             fileInfo.length = 0;
@@ -277,7 +278,7 @@ var Listview = class Listview {
             this._saveDir = Gio.Application.get_default().saveDir;
         }
         if (eventType === Gio.FileMonitorEvent.DELETED ||
-            eventType === Gio.FileMonitorEvent.CHANGES_DONE_HINT && MainWindow.recordPipeline === 
MainWindow.RecordPipelineStates.STOPPED) {
+            eventType === Gio.FileMonitorEvent.CHANGES_DONE_HINT && Record.pipeState === 
Record.PipelineStates.STOPPED) {
             stopVal = EnumeratorState.ACTIVE;
             allFilesInfo.length = 0;
             fileInfo.length = 0;
diff --git a/src/mainWindow.js b/src/mainWindow.js
index e5bd612..ba57453 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -22,18 +22,16 @@
 */
 
 const Gio = imports.gi.Gio;
-const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
-const Gst = imports.gi.Gst;
 const Gtk = imports.gi.Gtk;
-const Pango = imports.gi.Pango;
 
 const Settings = imports.preferences.settings;
 const AudioProfile = imports.audioProfile;
 const Utils = imports.utils;
-const Info = imports.info;
 const Listview = imports.listview;
-const Play = imports.play;
+const Row = imports.row.Row;
+const RowState = imports.row.RowState;
+const Player = imports.player.Player;
 const Record = imports.record;
 const Waveform = imports.waveform;
 
@@ -41,12 +39,9 @@ let activeProfile = null;
 var audioProfile = null;
 var displayTime = null;
 var list = null;
-var play = null;
-let previousSelRow = null;
+var player = null;
 var recordPipeline = null;
-let setVisibleID = null;
 var view = null;
-var volumeValue = [];
 var wave = null;
 
 var ActiveArea = {
@@ -54,21 +49,6 @@ var ActiveArea = {
     PLAY: 1,
 };
 
-const PipelineStates = {
-    PLAYING: 0,
-    PAUSED: 1,
-    STOPPED: 2,
-};
-
-var RecordPipelineStates = {
-    PLAYING: 0,
-    PAUSED: 1,
-    STOPPED: 2,
-};
-
-const _TIME_DIVISOR = 60;
-var _SEC_TIMEOUT = 100;
-
 var MainWindow = GObject.registerClass({
     Template: 'resource:///org/gnome/SoundRecorder/ui/window.ui',
     InternalChildren: ['recordButton', 'appMenuButton', 'mainStack', 'mainView', 'emptyView'],
@@ -79,8 +59,7 @@ var MainWindow = GObject.registerClass({
         displayTime = new Utils.DisplayTime();
         view = this;
         this._addListviewPage();
-        this.labelID = null;
-        play = new Play.Play();
+        player = new Player();
 
         super._init(Object.assign({
             icon_name: pkg.name,
@@ -99,15 +78,12 @@ var MainWindow = GObject.registerClass({
     }
 
     _onRecord() {
-        view.hasPreviousSelRow();
-
         if (view.listBox)
             view.listBox.set_selection_mode(Gtk.SelectionMode.NONE);
         else
             this._mainStack.set_visible_child(this._mainView);
 
         this._recordButton.set_sensitive(false);
-        setVisibleID = ActiveArea.RECORD;
         view.recordGrid.show_all();
 
         if (activeProfile === null)
@@ -118,10 +94,6 @@ var MainWindow = GObject.registerClass({
         wave = new Waveform.WaveForm(view.recordGrid, null);
     }
 
-    _addEmptyPage() {
-        this._mainStack.set_visible_child(this._emptyView);
-    }
-
     _addListviewPage() {
         list = new Listview.Listview();
         list.setListTypeNew();
@@ -129,67 +101,16 @@ var MainWindow = GObject.registerClass({
         this._record = new Record.Record(audioProfile);
     }
 
-    onPlayStopClicked() {
-        if (play.getPipeStates() === PipelineStates.PLAYING) {
-            play.stopPlaying();
-            let listRow = this.listBox.get_selected_row();
-            let rowGrid = listRow.get_child();
-            rowGrid.foreach(child => {
-                if (child.name === 'PauseButton') {
-                    child.hide();
-                    child.sensitive = false;
-                } else if (child.name === 'PlayLabelBox') {
-                    child.show();
-                    child.foreach(grandchild => {
-                        if (grandchild.name === 'PlayTimeLabel')
-                            grandchild.hide();
-
-
-                        if (grandchild.name === 'DividerLabel')
-                            grandchild.hide();
-
-                    });
-                } else {
-                    child.show();
-                    child.sensitive = true;
-                }
-            });
-        }
-    }
-
     onRecordStopClicked() {
+        Record.pipeState = Record.PipelineStates.STOPPED;
         this._record.stopRecording();
         this.recordGrid.hide();
-        recordPipeline = RecordPipelineStates.STOPPED;
         this._recordButton.set_sensitive(true);
-        if (this.listBox !== null)
-            this.listBox.set_selection_mode(Gtk.SelectionMode.SINGLE);
-    }
-
-    _formatTime(unformattedTime) {
-        this.unformattedTime = unformattedTime;
-        let seconds = Math.floor(this.unformattedTime);
-        let hours = parseInt(seconds / Math.pow(_TIME_DIVISOR, 2));
-        let hoursString = '';
-
-        if (hours > 10)
-            hoursString = `${hours}:`;
-        else if (hours < 10 && hours > 0)
-            hoursString = `0${hours}:`;
-
-        let minuteString = parseInt(seconds / _TIME_DIVISOR) % _TIME_DIVISOR;
-        let secondString = parseInt(seconds % _TIME_DIVISOR);
-        let timeString =
-            `${hoursString +
-            (minuteString < 10 ? `0${minuteString}` : minuteString)
-            }:${
-                secondString < 10 ? `0${secondString}` : secondString}`;
-
-        return timeString;
+        wave = null;
     }
 
     _updatePositionCallback() {
-        let position = MainWindow.play.queryPosition();
+        let position = player.queryPosition();
 
         if (position >= 0)
             this.progressScale.set_value(position);
@@ -197,22 +118,7 @@ var MainWindow = GObject.registerClass({
         return true;
     }
 
-    setVolume() {
-        if (setVisibleID === ActiveArea.PLAY)
-            play.setVolume(volumeValue[0].play);
-        else if (setVisibleID === ActiveArea.RECORD)
-            this._record.setVolume(volumeValue[0].record);
-
-    }
-
-    getVolume() {
-        return this.playVolume.get_value();
-    }
-
     listBoxAdd() {
-        let playVolume = Settings.speakerVolume;
-        let micVolume = Settings.micVolume;
-        volumeValue.push({ record: micVolume, play: playVolume });
         activeProfile = Settings.mediaCodec;
 
         this.recordGrid = new Gtk.Grid({ name: 'recordGrid',
@@ -274,174 +180,35 @@ var MainWindow = GObject.registerClass({
 
         if (list.getItemCount() === 0) {
             this._scrolledWin.get_style_context().add_class('emptyGrid');
-            this._addEmptyPage();
+            this._mainStack.set_visible_child(this._emptyView);
         } else {
             this.listBox = new Gtk.ListBox({ vexpand: true });
             this._scrolledWin.add(this.listBox);
             this.listBox.set_selection_mode(Gtk.SelectionMode.SINGLE);
             this.listBox.set_header_func(null);
             this.listBox.set_activate_on_single_click(true);
-            this.listBox.connect('row-selected', () => {
-                this.rowGridCallback();
-            });
             this.listBox.show();
 
             this._files = [];
             this._files = list.getFilesInfoForList();
 
-            this._files.forEach((file, index) => {
-
-                this.rowGrid = new Gtk.Grid({ name: index.toString(),
-                    height_request: 45,
-                    orientation: Gtk.Orientation.VERTICAL,
-                    hexpand: true,
-                    vexpand: true });
-                this.rowGrid.set_orientation(Gtk.Orientation.HORIZONTAL);
-                this.listBox.add(this.rowGrid);
-                this.rowGrid.show();
-
-                // play button
-                this.playImage = new Gtk.Image({ name: 'PlayImage' });
-                this.playImage.set_from_icon_name('media-playback-start-symbolic', Gtk.IconSize.BUTTON);
-                this._playListButton = new Gtk.Button({ name: 'PlayButton',
-                    hexpand: false,
-                    vexpand: true });
-                this._playListButton.set_image(this.playImage);
-                this._playListButton.set_tooltip_text(_('Play'));
-                this.rowGrid.attach(this._playListButton, 0, 0, 2, 2);
-                this._playListButton.show();
-                this._playListButton.connect('clicked', button => { // eslint-disable-line
-                    let row = button.get_parent().get_parent();
-                    this.listBox.select_row(row);
-                    play.passSelected(row);
-                    this.onPlayPauseToggled(row, file);
-                });
-
-                // pause button
-                this.pauseImage = Gtk.Image.new();
-                this.pauseImage.set_from_icon_name('media-playback-pause-symbolic', Gtk.IconSize.BUTTON);
-                this._pauseListButton = new Gtk.Button({ name: 'PauseButton',
-                    hexpand: false,
-                    vexpand: true });
-                this._pauseListButton.set_image(this.pauseImage);
-                this._pauseListButton.set_tooltip_text(_('Pause'));
-                this.rowGrid.attach(this._pauseListButton, 0, 0, 2, 2);
-                this._pauseListButton.hide();
-                this._pauseListButton.connect('clicked', button => {
-                    let row = button.get_parent().get_parent();
-                    this.listBox.select_row(row);
-                    this.onPause(row);
-                });
-
-                this._fileName = new Gtk.Label({ name: 'FileNameLabel',
-                    ellipsize: Pango.EllipsizeMode.END,
-                    halign: Gtk.Align.START,
-                    valign: Gtk.Align.START,
-                    margin_start: 15,
-                    margin_top: 5,
-                    use_markup: true,
-                    width_chars: 35,
-                    xalign: 0 });
-                let markup = `<b>${file.fileName}</b>`;
-                this._fileName.label = markup;
-                this._fileName.set_no_show_all(true);
-                this.rowGrid.attach(this._fileName, 3, 0, 10, 3);
-                this._fileName.show();
-
-                this._playLabelBox = new Gtk.Box({ name: 'PlayLabelBox',
-                    orientation: Gtk.Orientation.HORIZONTAL,
-                    height_request: 45 });
-                this.rowGrid.attach(this._playLabelBox, 3, 1, 5, 1);
-                this._playLabelBox.show();
-                this.playDurationLabel = new Gtk.Label({ name: 'PlayDurationLabel',
-                    halign: Gtk.Align.END,
-                    valign: Gtk.Align.END,
-                    margin_start: 15,
-                    margin_top: 5 });
-                this.fileDuration = this._formatTime(file.duration / Gst.SECOND);
-                this.playDurationLabel.label = this.fileDuration;
-                this._playLabelBox.pack_start(this.playDurationLabel, false, true, 0);
-                this.playDurationLabel.show();
-
-                this.dividerLabel = new Gtk.Label({ name: 'DividerLabel',
-                    halign: Gtk.Align.START,
-                    valign: Gtk.Align.END,
-                    margin_top: 5 });
-                this.dividerLabel.label = '/';
-                this._playLabelBox.pack_start(this.dividerLabel, false, true, 0);
-                this.dividerLabel.hide();
-
-                this.playTimeLabel = new Gtk.Label({ name: 'PlayTimeLabel',
-                    halign: Gtk.Align.START,
-                    valign: Gtk.Align.END,
-                    margin_end: 15,
-                    margin_top: 5 });
-                this.playTimeLabel.label = '0:00';
-                this._playLabelBox.pack_start(this.playTimeLabel, false, true, 0);
-                this.playTimeLabel.hide();
-
-                // Date Modified label
-                this.dateModifiedLabel = new Gtk.Label({ name: 'DateModifiedLabel',
-                    halign: Gtk.Align.END,
-                    valign: Gtk.Align.END,
-                    margin_start: 15,
-                    margin_top: 5 });
-                this.dateModifiedLabel.label = file.dateModified;
-                this.dateModifiedLabel.get_style_context().add_class('dim-label');
-                this.dateModifiedLabel.set_no_show_all(true);
-                this.rowGrid.attach(this.dateModifiedLabel, 3, 1, 6, 1);
-                this.dateModifiedLabel.show();
-
-                this.waveFormGrid = new Gtk.Grid({ name: 'WaveFormGrid',
-                    hexpand: true,
-                    vexpand: true,
-                    orientation: Gtk.Orientation.VERTICAL,
-                    valign: Gtk.Align.FILL });
-                this.waveFormGrid.set_no_show_all(true);
-                this.rowGrid.attach(this.waveFormGrid, 12, 1, 17, 2);
-                this.waveFormGrid.show();
-
-                // info button
-                this._info = new Gtk.Button({ name: 'InfoButton',
-                    hexpand: false,
-                    vexpand: true,
-                    margin_end: 2 });
-                this._info.image = Gtk.Image.new_from_icon_name('dialog-information-symbolic', 
Gtk.IconSize.BUTTON);
-                this._info.connect('clicked', button => {
-                    let row = button.get_parent().get_parent();
-                    this.listBox.select_row(row);
-                    (new Info.InfoDialog(file)).show();
-                });
-                this._info.set_tooltip_text(_('Info'));
-                this.rowGrid.attach(this._info, 27, 0, 1, 2);
-                this._info.hide();
-
-                // delete button
-                this._delete = new Gtk.Button({ name: 'DeleteButton',
-                    hexpand: false,
-                    margin_start: 2 });
-                this._delete.image = Gtk.Image.new_from_icon_name('user-trash-symbolic', 
Gtk.IconSize.BUTTON);
-                this._delete.connect('clicked', button => {
-                    let row = button.get_parent().get_parent();
-                    this.listBox.select_row(row);
-                    this._deleteFile(row);
+            this._files.forEach(file => {
+                let row = new Row(file);
+                row.connect('play', (playingRow, fileUri) => {
+                    this.listBox.get_children().forEach(_row => {
+                        if (_row !== playingRow)
+                            _row.setState(RowState.PAUSED);
+                    });
+                    player.startPlaying(fileUri);
                 });
-                this._delete.set_tooltip_text(_('Delete'));
-                this.rowGrid.attach(this._delete, 28, 0, 1, 2);
-                this._delete.hide();
-
+                row.connect('pause', () => player.pausePlaying());
+                this.listBox.add(row);
             });
         }
         list.monitorListview();
     }
 
     listBoxRefresh() {
-        previousSelRow = null;
-
-        if (this.listBox)
-            this.listBox.set_selection_mode(Gtk.SelectionMode.NONE);
-
-
         list.setListTypeRefresh();
         list.enumerateDirectory();
     }
@@ -451,187 +218,9 @@ var MainWindow = GObject.registerClass({
         this.scrolledWinAdd();
     }
 
-    hasPreviousSelRow() {
-        if (previousSelRow !== null) {
-            let rowGrid = previousSelRow.get_child();
-            rowGrid.foreach(child => {
-                let alwaysShow = child.get_no_show_all();
-
-                if (!alwaysShow)
-                    child.hide();
-
-                if (child.name === 'PauseButton') {
-                    child.hide();
-                    child.sensitive = false;
-                }
-                if (child.name === 'PlayButton') {
-                    child.show();
-                    child.sensitive = true;
-                }
-
-                if (child.name === 'PlayLabelBox') {
-                    child.show();
-                    child.foreach(grandchild => {
-                        if (grandchild.name === 'PlayTimeLabel')
-                            grandchild.hide();
-
-
-                        if (grandchild.name === 'DividerLabel')
-                            grandchild.hide();
-
-                    });
-                }
-            });
-
-            if (play.getPipeStates() === PipelineStates.PLAYING || play.getPipeStates() === 
PipelineStates.PAUSED)
-                play.stopPlaying();
-
-        }
-        previousSelRow = null;
-    }
-
-    rowGridCallback() {
-        let selectedRow = this.listBox.get_selected_row();
-
-        if (selectedRow) {
-            if (previousSelRow !== null)
-                this.hasPreviousSelRow();
-
-
-            previousSelRow = selectedRow;
-            let selectedRowGrid = previousSelRow.get_child();
-            selectedRowGrid.show_all();
-            selectedRowGrid.foreach(child => {
-                let alwaysShow = child.get_no_show_all();
-
-                if (!alwaysShow)
-                    child.sensitive = true;
-
-                if (child.name === 'PauseButton') {
-                    child.hide();
-                    child.sensitive = false;
-                }
-
-                if (child.name === 'WaveFormGrid')
-                    child.sensitive = true;
-            });
-        }
-    }
-
-    _getFileFromRow(selected) {
-        let fileForAction = null;
-        let rowGrid = selected.get_child();
-        rowGrid.foreach(child => {
-            if (child.name === 'FileNameLabel') {
-                let name = child.get_text();
-                let application = Gio.Application.get_default();
-                fileForAction = application.saveDir.get_child_for_display_name(name);
-            }
-        });
-
-        return fileForAction;
-    }
-
-    _deleteFile(selected) {
-        let fileToDelete = this._getFileFromRow(selected);
-        fileToDelete.trash_async(GLib.PRIORITY_DEFAULT, null, null);
-    }
-
-    loadPlay(selected) {
-        let fileToPlay = this._getFileFromRow(selected);
-
-        return fileToPlay;
-    }
-
-    setLabel(time) {
-        this.time = time;
-
-        this.timeLabelString = this._formatTime(time);
-
-        if (setVisibleID === ActiveArea.RECORD) {
-            this.recordTimeLabel.label = this.timeLabelString;
-            this.recordTimeLabel.get_style_context().add_class('dim-label');
-        } else if (setVisibleID === ActiveArea.PLAY) {
-            this.playTimeLabel.label = this.timeLabelString;
-        }
-    }
-
-    setNameLabel(newName, oldName, index) {
-
-        let selected = this.listBox.get_row_at_index(index);
-        let rowGrid = selected.get_child();
-        rowGrid.foreach(child => {
-            if (child.name === 'FileNameLabel') {
-                let markup = `<b>${newName}</b>`;
-                child.label = markup;
-            }
-        });
-        rowGrid.set_name(newName);
-    }
-
-    onPause(listRow) {
-        let activeState = play.getPipeStates();
-
-        if (activeState === PipelineStates.PLAYING) {
-            play.pausePlaying();
-
-            let rowGrid = listRow.get_child();
-            rowGrid.foreach(child => {
-                if (child.name === 'PauseButton') {
-                    child.hide();
-                    child.sensitive = false;
-                }
-
-                if (child.name === 'PlayButton') {
-                    child.show();
-                    child.sensitive = true;
-                }
-            });
-        }
-    }
-
-    onPlayPauseToggled(listRow, selFile) {
-        setVisibleID = ActiveArea.PLAY;
-        let activeState = play.getPipeStates();
-
-        if (activeState !== PipelineStates.PLAYING) {
-            play.startPlaying();
-
-
-            let rowGrid = listRow.get_child();
-            rowGrid.foreach(child => {
-                if (child.name === 'InfoButton' || child.name === 'DeleteButton' ||
-                    child.name === 'PlayButton') {
-                    child.hide();
-                    child.sensitive = false;
-                }
-
-                if (child.name === 'PauseButton') {
-                    child.show();
-                    child.sensitive = true;
-                }
-
-                if (child.name === 'PlayLabelBox') {
-                    child.foreach(grandchild => {
-                        if (grandchild.name === 'PlayTimeLabel')
-                            view.playTimeLabel = grandchild;
-
-
-                        if (grandchild.name === 'DividerLabel')
-                            grandchild.show();
-
-                    });
-                }
-
-                if (child.name === 'WaveFormGrid') {
-                    this.wFGrid = child;
-                    child.sensitive = true;
-                }
-            });
-
-            if (activeState !== PipelineStates.PAUSED)
-                wave = new Waveform.WaveForm(this.wFGrid, selFile);
-
-        }
+    setRecordTimeLabel(time) {
+        this.timeLabelString = Utils.StringUtils.formatTime(time);
+        this.recordTimeLabel.label = this.timeLabelString;
+        this.recordTimeLabel.get_style_context().add_class('dim-label');
     }
 });
diff --git a/src/org.gnome.SoundRecorder.src.gresource.xml.in 
b/src/org.gnome.SoundRecorder.src.gresource.xml.in
index 91c3f40..32ce3fe 100644
--- a/src/org.gnome.SoundRecorder.src.gresource.xml.in
+++ b/src/org.gnome.SoundRecorder.src.gresource.xml.in
@@ -6,9 +6,10 @@
     <file>utils.js</file>
     <file>info.js</file>
     <file>listview.js</file>
+    <file>row.js</file>
     <file>main.js</file>
     <file>mainWindow.js</file>
-    <file>play.js</file>
+    <file>player.js</file>
     <file>preferences.js</file>
     <file>record.js</file>
     <file>waveform.js</file>
diff --git a/src/play.js b/src/player.js
similarity index 74%
rename from src/play.js
rename to src/player.js
index c9875aa..78dabc8 100644
--- a/src/play.js
+++ b/src/player.js
@@ -26,8 +26,9 @@ const Gtk = imports.gi.Gtk;
 
 const Application = imports.application;
 const MainWindow = imports.mainWindow;
+const Settings = imports.preferences;
 
-const PipelineStates = {
+var PipelineStates = {
     PLAYING: 0,
     PAUSED: 1,
     STOPPED: 2,
@@ -43,17 +44,17 @@ let errorDialogState;
 
 const _TENTH_SEC = 100000000;
 
-var Play = class Play {
-    _playPipeline() {
+var Player = class Player { // eslint-disable-line no-unused-vars
+    _playPipeline(fileUri) {
         errorDialogState = ErrState.OFF;
-        let uri = this._fileToPlay.get_uri();
-        this.play = Gst.ElementFactory.make('playbin', 'play');
-        this.play.set_property('uri', uri);
+        this.player = Gst.ElementFactory.make('playbin', 'play');
+        this.player.set_property('uri', fileUri);
         this.sink = Gst.ElementFactory.make('pulsesink', 'sink');
-        this.play.set_property('audio-sink', this.sink);
-        this.clock = this.play.get_clock();
-        this.playBus = this.play.get_bus();
+        this.player.set_property('audio-sink', this.sink);
+        this.clock = this.player.get_clock();
+        this.playBus = this.player.get_bus();
         this.playBus.add_signal_watch();
+        this.playState = PipelineStates.NULL;
         this.playBus.connect('message', (playBus, message) => {
             if (message !== null)
                 this._onMessageReceived(message);
@@ -61,34 +62,39 @@ var Play = class Play {
         });
     }
 
-    startPlaying() {
+    startPlaying(fileUri) {
+        this.stopPlaying();
+
+        log(`[Player] Playing ${fileUri}`);
         this.baseTime = 0;
 
-        if (!this.play || this.playState === PipelineStates.STOPPED)
-            this._playPipeline();
+        if (!this.player || this.playState === PipelineStates.STOPPED)
+            this._playPipeline(fileUri);
 
 
         if (this.playState === PipelineStates.PAUSED) {
             this.updatePosition();
-            this.play.set_base_time(this.clock.get_time());
-            this.baseTime = this.play.get_base_time() - this.runTime;
+            this.player.set_base_time(this.clock.get_time());
+            this.baseTime = this.player.get_base_time() - this.runTime;
         }
 
-        this.ret = this.play.set_state(Gst.State.PLAYING);
+        this.ret = this.player.set_state(Gst.State.PLAYING);
         this.playState = PipelineStates.PLAYING;
 
         if (this.ret === Gst.StateChangeReturn.FAILURE) {
             this._showErrorDialog(_('Unable to play recording'));
             errorDialogState = ErrState.ON;
         } else if (this.ret === Gst.StateChangeReturn.SUCCESS) {
-            MainWindow.view.setVolume();
+            let value = Settings.settings.speakerVolume;
+            this.player.set_volume(GstAudio.StreamVolumeFormat.CUBIC, value);
         }
         GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, Application.SIGINT, 
Application.application.onWindowDestroy);
         GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, Application.SIGTERM, 
Application.application.onWindowDestroy);
     }
 
     pausePlaying() {
-        this.play.set_state(Gst.State.PAUSED);
+        log('[Player] Paused');
+        this.player.set_state(Gst.State.PAUSED);
         this.playState = PipelineStates.PAUSED;
 
         if (this.timeout) {
@@ -98,14 +104,14 @@ var Play = class Play {
     }
 
     stopPlaying() {
-        if (this.playState !== PipelineStates.STOPPED)
+        log('[Player] Stopped');
+        if (this.player !== undefined)
             this.onEnd();
-
     }
 
     onEnd() {
-        this.play.set_state(Gst.State.NULL);
         this.playState = PipelineStates.STOPPED;
+        this.player.set_state(Gst.State.NULL);
         this.playBus.remove_signal_watch();
         this._updateTime();
 
@@ -120,17 +126,13 @@ var Play = class Play {
         errorDialogState = ErrState.OFF;
     }
 
-    onEndOfStream() {
-        MainWindow.view.onPlayStopClicked();
-    }
-
     _onMessageReceived(message) {
         this.localMsg = message;
         let msg = message.type;
         switch (msg) {
 
         case Gst.MessageType.EOS: {
-            this.onEndOfStream();
+            this.stopPlaying();
             break;
         }
 
@@ -149,7 +151,7 @@ var Play = class Play {
 
         case Gst.MessageType.ASYNC_DONE: {
             if (this.sought) {
-                this.play.set_state(this._lastState);
+                this.player.set_state(this._lastState);
                 MainWindow.view.setProgressScaleSensitive();
             }
             this.updatePosition();
@@ -163,7 +165,7 @@ var Play = class Play {
 
         case Gst.MessageType.NEW_CLOCK: {
             if (this.playState === PipelineStates.PAUSED) {
-                this.clock = this.play.get_clock();
+                this.clock = this.player.get_clock();
                 this.startPlaying();
             }
             break;
@@ -177,20 +179,20 @@ var Play = class Play {
     }
 
     _updateTime() {
-        let time = this.play.query_position(Gst.Format.TIME)[1] / Gst.SECOND;
-        this.trackDuration = this.play.query_duration(Gst.Format.TIME)[1];
+        // let time = this.player.query_position(Gst.Format.TIME)[1] / Gst.SECOND;
+        this.trackDuration = this.player.query_duration(Gst.Format.TIME)[1];
         this.trackDurationSecs = this.trackDuration / Gst.SECOND;
 
-        if (time >= 0 && this.playState !== PipelineStates.STOPPED)
-            MainWindow.view.setLabel(time);
-        else if (time >= 0 && this.playState === PipelineStates.STOPPED)
-            MainWindow.view.setLabel(0);
+        // if (time >= 0 && this.playState !== PipelineStates.STOPPED)
+        //       this._timeCallbackFn(time);
+        // else if (time >= 0 && this.playState === PipelineStates.STOPPED)
+        //       this._timeCallbackFn(0);
 
 
         let absoluteTime = 0;
 
         if  (this.clock === null)
-            this.clock = this.play.get_clock();
+            this.clock = this.player.get_clock();
 
         try {
             absoluteTime = this.clock.get_time();
@@ -214,7 +216,7 @@ var Play = class Play {
     queryPosition() {
         let position = 0;
         while (position === 0)
-            position = this.play.query_position(Gst.Format.TIME)[1] / Gst.SECOND;
+            position = this.player.query_position(Gst.Format.TIME)[1] / Gst.SECOND;
 
 
         return position;
@@ -227,15 +229,6 @@ var Play = class Play {
         }
     }
 
-    setVolume(value) {
-        this.play.set_volume(GstAudio.StreamVolumeFormat.CUBIC, value);
-    }
-
-    passSelected(selected) {
-        this._selected = selected;
-        this._fileToPlay = MainWindow.view.loadPlay(this._selected);
-    }
-
     _showErrorDialog(errorStrOne, errorStrTwo) {
         if (errorDialogState === ErrState.OFF) {
             let errorDialog = new Gtk.MessageDialog({ destroy_with_parent: true,
@@ -251,7 +244,7 @@ var Play = class Play {
             errorDialog.set_transient_for(Gio.Application.get_default().get_active_window());
             errorDialog.connect('response', () => {
                 errorDialog.destroy();
-                this.onEndOfStream();
+                this.stopPlaying();
             });
             errorDialog.show();
         }
diff --git a/src/preferences.js b/src/preferences.js
index 9fccedf..8d76768 100644
--- a/src/preferences.js
+++ b/src/preferences.js
@@ -22,8 +22,6 @@ const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
 const GObject = imports.gi.GObject;
 
-const MainWindow = imports.mainWindow;
-
 let _settings = new Gio.Settings({ schema: pkg.name });
 
 var settings = {
@@ -81,18 +79,15 @@ var SettingsDialog = GObject.registerClass({ // eslint-disable-line no-unused-va
             settings.channel = this._channelsComboBox.get_active();
         });
 
-        let volumeValue = MainWindow.volumeValue[0];
-        this._volumeScale.set_value(volumeValue.play);
+        this._volumeScale.set_value(settings.speakerVolume);
         this._volumeScale.connect('value-changed', () => {
             let vol = this._volumeScale.get_value();
-            volumeValue.play = vol;
             settings.speakerVolume = vol;
         });
 
-        this._microphoneScale.set_value(volumeValue.record);
+        this._microphoneScale.set_value(settings.micVolume);
         this._microphoneScale.connect('value-changed', () => {
             let vol = this._microphoneScale.get_value();
-            volumeValue.record = vol;
             settings.micVolume = vol;
         });
     }
diff --git a/src/record.js b/src/record.js
index d9fc1ea..632db3d 100644
--- a/src/record.js
+++ b/src/record.js
@@ -26,10 +26,10 @@ const GstPbutils = imports.gi.GstPbutils;
 const Gtk = imports.gi.Gtk;
 
 const Application = imports.application;
-const Settings = imports.preferences.settings;
+const Settings = imports.preferences;
 const MainWindow = imports.mainWindow;
 
-const PipelineStates = {
+var PipelineStates = {
     PLAYING: 0,
     PAUSED: 1,
     STOPPED: 2,
@@ -46,6 +46,7 @@ const Channels = {
 };
 
 const _TENTH_SEC = 100000000;
+const _SEC_TIMEOUT = 100;
 
 let errorDialogState;
 
@@ -147,7 +148,7 @@ var Record = class Record {
         let time = this.pipeline.query_position(Gst.Format.TIME)[1] / Gst.SECOND;
 
         if (time >= 0)
-            this._view.setLabel(time, 0);
+            this._view.setRecordTimeLabel(time, 0);
 
 
         return true;
@@ -174,11 +175,11 @@ var Record = class Record {
             errorDialogState = ErrState.ON;
             this._buildFileName.getTitle().delete_async(GLib.PRIORITY_DEFAULT, null, null);
         } else {
-            MainWindow.view.setVolume();
+            this.volume.set_volume(GstAudio.StreamVolumeFormat.CUBIC, Settings.settings.micVolume);
         }
 
         if (!this.timeout)
-            this.timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MainWindow._SEC_TIMEOUT, () => 
this._updateTime());
+            this.timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, _SEC_TIMEOUT, () => this._updateTime());
 
     }
 
@@ -242,8 +243,7 @@ var Record = class Record {
                         if (val > 0)
                             val = 0;
 
-                        let value = Math.pow(10, val / 20);
-                        this.peak = value;
+                        this.peak = Math.pow(10, val / 20);
 
 
                         if  (this.clock === null)
@@ -261,7 +261,9 @@ var Record = class Record {
 
                         this.runTime = this.absoluteTime - this.baseTime;
                         let approxTime = Math.round(this.runTime / _TENTH_SEC);
-                        MainWindow.wave._drawEvent(approxTime, this.peak);
+
+                        if (MainWindow.wave !== null)
+                            MainWindow.wave._drawEvent(approxTime, this.peak);
                     }
                 }
             }
@@ -288,12 +290,6 @@ var Record = class Record {
         }
     }
 
-    setVolume(value) {
-        if (this.volume)
-            this.volume.set_volume(GstAudio.StreamVolumeFormat.CUBIC, value);
-
-    }
-
     _getChannels() {
 
         let channels = null;
diff --git a/src/row.js b/src/row.js
new file mode 100644
index 0000000..7d071d7
--- /dev/null
+++ b/src/row.js
@@ -0,0 +1,56 @@
+const Gst = imports.gi.Gst;
+const Gtk = imports.gi.Gtk;
+const GObject = imports.gi.GObject;
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+
+var Info = imports.info;
+var Utils = imports.utils;
+
+var RowState = {
+    PLAYING: 0,
+    PAUSED: 1,
+};
+
+var Row = GObject.registerClass({ // eslint-disable-line no-unused-vars
+    Template: 'resource:///org/gnome/SoundRecorder/ui/row.ui',
+    InternalChildren: ['playbackStack', 'fileNameLabel', 'fileDurationLabel', 'playButton', 'pauseButton', 
'infoButton', 'deleteButton'],
+    Signals: {
+        'play': { param_types: [GObject.TYPE_STRING] },
+        'pause': {},
+    },
+}, class Row extends Gtk.ListBoxRow {
+    _init(file) {
+        super._init({});
+        this.file = file;
+
+        this._fileNameLabel.label = file.fileName;
+        this._fileDurationLabel.label = Utils.StringUtils.formatTime(file.duration / Gst.SECOND);
+
+        this._playButton.connect('clicked', () => {
+            this.setState(RowState.PLAYING);
+            this.emit('play', this.file.uri);
+        });
+
+        this._pauseButton.connect('clicked', () => {
+            this.setState(RowState.PAUSED);
+            this.emit('pause');
+        });
+
+        this._infoButton.connect('clicked', () => (new Info.InfoDialog(file)).show());
+        this._deleteButton.connect('clicked', () => {
+            let gioFile = Gio.File.new_for_uri(file.uri);
+            gioFile.trash_async(GLib.PRIORITY_DEFAULT, null, null);
+        });
+    }
+
+    setState(rowState) {
+        if (rowState === RowState.PLAYING) {
+            this._playbackStack.set_visible_child_name('pause');
+            this._deleteButton.set_sensitive(false);
+        } else if (rowState === RowState.PAUSED) {
+            this._playbackStack.set_visible_child_name('play');
+            this._deleteButton.set_sensitive(true);
+        }
+    }
+});
diff --git a/src/utils.js b/src/utils.js
index c3daefe..f17103f 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -21,6 +21,8 @@
 const Gettext = imports.gettext;
 const GLib = imports.gi.GLib;
 
+const _TIME_DIVISOR = 60;
+
 
 var DisplayTime = class DisplayTime {
     getDisplayTime(mtime) {
@@ -62,4 +64,26 @@ var DisplayTime = class DisplayTime {
         }
         return text;
     }
+
+};
+
+
+var StringUtils = { // eslint-disable-line no-unused-vars
+    formatTime: unformattedTime => {
+        this.unformattedTime = unformattedTime;
+        let seconds = Math.floor(this.unformattedTime);
+        let hours = parseInt(seconds / Math.pow(_TIME_DIVISOR, 2));
+        let hoursString = '';
+
+        if (hours > 10)
+            hoursString = `${hours}:`;
+        else if (hours < 10 && hours > 0)
+            hoursString = `0${hours}:`;
+
+        let minuteString = parseInt(seconds / _TIME_DIVISOR) % _TIME_DIVISOR;
+        let secondString = parseInt(seconds % _TIME_DIVISOR);
+        let timeString = `${hoursString + (minuteString < 10 ? `0${minuteString}` : 
minuteString)}:${secondString < 10 ? `0${secondString}` : secondString}`;
+
+        return timeString;
+    },
 };



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