[gnome-sound-recorder] row: rearrange buttons & added skip playback



commit 40c2807ceec70a44430e9211dec100506e24bef5
Author: Kavan Mevada <kavanmevada gmail com>
Date:   Wed Jul 15 18:02:36 2020 +0530

    row: rearrange buttons & added skip playback

 data/application.css                            |   7 +
 data/icons/skip-back-symbolic.svg               |  99 +++++++++
 data/icons/skip-forward-symbolic.svg            |  95 +++++++++
 data/org.gnome.SoundRecorder.data.gresource.xml |   5 +-
 data/ui/row.ui                                  | 256 +++++++++++++++++-------
 data/ui/window.ui                               |   4 +
 src/application.js                              |   1 +
 src/player.js                                   |  62 +++++-
 src/recording.js                                |   4 +-
 src/recordingsListBox.js                        |  22 +-
 src/row.js                                      |  43 ++--
 11 files changed, 491 insertions(+), 107 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index 961c753..0aad6c1 100644
--- a/data/application.css
+++ b/data/application.css
@@ -6,12 +6,19 @@
 .pill-button {
   border-radius: 9999px;
   -gtk-outline-radius: 9999px;
+  padding-left: 9px;
+  padding-right: 9px;
 }
 
 .large-button {
   padding: 12px 12px;
 }
 
+
+row label.title {
+  font-weight: bold;
+}
+
 row label.subtitle {
   font-size: smaller;
 }
\ No newline at end of file
diff --git a/data/icons/skip-back-symbolic.svg b/data/icons/skip-back-symbolic.svg
new file mode 100644
index 0000000..dc560f0
--- /dev/null
+++ b/data/icons/skip-back-symbolic.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb";
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16"
+   version="1.1"
+   id="svg7384"
+   height="16"
+   sodipodi:docname="skip-back-symbolic.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1016"
+     id="namedview16"
+     showgrid="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-midpoints="true"
+     inkscape:object-paths="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:snap-object-midpoints="true"
+     inkscape:snap-center="true"
+     inkscape:snap-text-baseline="true"
+     inkscape:snap-page="true"
+     inkscape:zoom="14.75"
+     inkscape:cx="-5.302011"
+     inkscape:cy="11.053898"
+     inkscape:window-x="1920"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g1104">
+    <inkscape:grid
+       type="xygrid"
+       id="grid837" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata90">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title>Gnome Symbolic Icon Theme</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <title
+     id="title9167">Gnome Symbolic Icon Theme</title>
+  <defs
+     id="defs7386">
+    <linearGradient
+       osb:paint="solid"
+       id="linearGradient7212">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop7214" />
+    </linearGradient>
+  </defs>
+  <g
+     id="g1104"
+     transform="translate(-285.00026,-511.51971)">
+    <path
+       
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:'Bitstream
 Vera Sans';-inkscape-font-specification:'Bitstream Vera 
Sans';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
+       d="m 293.25027,512.51971 c -0.13304,0.006 -0.26338,0.0444 -0.375,0.11719 l -3.75,2.25 c 
-0.2118,0.13478 -0.32813,0.3838 -0.32813,0.63281 0,0.24901 0.11633,0.49803 0.32813,0.63281 l 3.75,2.25 c 
0.11162,0.0728 0.24196,0.11119 0.375,0.11719 h 0.11719 0.6328 v -6 h -0.6328 z"
+       id="path1096-6-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccscccccccc" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path1098-7"
+       d="m 294.00002,514.51953 c 2.61534,0 4.93816,1.703 5.72461,4.19727 0.78645,2.49427 -0.14084,5.22062 
-2.2832,6.7207 a 1.0000999,1.0000999 0 1 1 -1.14649,-1.63867 c 1.43403,-1.00411 2.04791,-2.8109 
1.52149,-4.48047 -0.52643,-1.66957 -2.06577,-2.79883 -3.81641,-2.79883 a 1.0000999,1.0000999 0 1 1 0,-2 z"
+       
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.
 
99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
 />
+    <path
+       d="m 285.51611,526.51971 h 3.72666 v -1.28266 h -1.066 v -4.732 h -0.89266 l -2.07134,1.196 
0.56334,1.07466 0.90133,-0.468 v 2.92934 h -1.16133 z"
+       
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:8.66666698px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell
 
Ultra-Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:0.99999976"
+       id="path844"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 292.11307,526.60638 c 1.52533,0 2.55666,-1.248 2.55666,-3.12867 0,-1.83733 -1.014,-3.05933 
-2.51333,-3.05933 -1.534,0 -2.56533,1.248 -2.56533,3.12 0,1.83733 1.014,3.068 2.522,3.068 z m 0.0347,-1.28267 
c -0.61533,0 -1.014,-0.73666 -1.014,-1.83733 0,-1.07467 0.39867,-1.78533 0.988,-1.78533 0.598,0 
1.00534,0.73666 1.00534,1.846 0,1.066 -0.39867,1.77666 -0.97934,1.77666 z"
+       
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:8.66666698px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell
 
Ultra-Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:0.99999976"
+       id="path846"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/data/icons/skip-forward-symbolic.svg b/data/icons/skip-forward-symbolic.svg
new file mode 100644
index 0000000..956b23a
--- /dev/null
+++ b/data/icons/skip-forward-symbolic.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb";
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16"
+   version="1.1"
+   id="svg7384"
+   height="16"
+   sodipodi:docname="skip-forward-symbolic.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1016"
+     id="namedview16"
+     showgrid="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-midpoints="true"
+     inkscape:object-paths="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:snap-object-midpoints="true"
+     inkscape:snap-center="true"
+     inkscape:snap-text-baseline="true"
+     inkscape:snap-page="true"
+     inkscape:zoom="20.85965"
+     inkscape:cx="12.060999"
+     inkscape:cy="12.860546"
+     inkscape:window-x="1920"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg7384">
+    <inkscape:grid
+       type="xygrid"
+       id="grid835" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata90">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title>Gnome Symbolic Icon Theme</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <title
+     id="title9167">Gnome Symbolic Icon Theme</title>
+  <defs
+     id="defs7386">
+    <linearGradient
+       osb:paint="solid"
+       id="linearGradient7212">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop7214" />
+    </linearGradient>
+  </defs>
+  <path
+     inkscape:connector-curvature="0"
+     id="path849"
+     
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:8.66666698px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell
 
Ultra-Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:0.99999976"
+     d="m 6.515284,15.000003 h 3.726667 V 13.717336 H 9.1759508 v -4.732 H 8.2832841 l -2.0713334,1.196 
0.5633333,1.074667 0.9013334,-0.468 v 2.929333 H 6.515284 Z" />
+  <path
+     inkscape:connector-curvature="0"
+     id="path851"
+     
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:8.66666698px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell
 
Ultra-Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:0.99999976"
+     d="m 13.112242,15.08667 c 1.525334,0 2.556667,-1.248001 2.556667,-3.128667 0,-1.837334 
-1.014,-3.0593337 -2.513333,-3.0593337 -1.534,0 -2.565334,1.2479997 -2.565334,3.1199997 0,1.837334 
1.014,3.068001 2.522,3.068001 z m 0.03467,-1.282667 c -0.615333,0 -1.014,-0.736667 -1.014,-1.837334 
0,-1.074666 0.398667,-1.785333 0.988,-1.785333 0.598,0 1.005333,0.736667 1.005333,1.846 0,1.066 
-0.398666,1.776667 -0.979333,1.776667 z" />
+  <path
+     
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:'Bitstream
 Vera Sans';-inkscape-font-specification:'Bitstream Vera 
Sans';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
+     d="m 7.74999,1 c 0.13304,0.006 0.26338,0.0444 0.375,0.11719 l 3.749999,2.2499999 c 0.2118,0.13478 
0.32813,0.3838 0.32813,0.63281 0,0.24901 -0.11633,0.49803 -0.32813,0.63281 L 8.12499,6.8828096 c 
-0.11162,0.0728 -0.24196,0.11119 -0.375,0.11719 H 7.6328 7 V 1 h 0.6328 z"
+     id="path946"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cccscccccccc" />
+  <path
+     
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.99
 
999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+     d="m 7,3 c -2.615338,-10e-8 -4.9362036,1.702994 -5.7226562,4.1972656 -0.78645273,2.4942717 
0.1388853,5.2206254 2.28125,6.7207034 A 1.0000999,1.0000999 0 1 0 4.7050781,12.279297 C 3.2710452,11.275191 
2.6571722,9.4683988 3.1835938,7.7988281 3.7100153,6.1292575 5.2493627,5 7,5 A 1.0000999,1.0000999 0 1 0 7,3 Z"
+     id="path948"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/data/org.gnome.SoundRecorder.data.gresource.xml b/data/org.gnome.SoundRecorder.data.gresource.xml
index 2fe2a70..e736be8 100644
--- a/data/org.gnome.SoundRecorder.data.gresource.xml
+++ b/data/org.gnome.SoundRecorder.data.gresource.xml
@@ -4,6 +4,7 @@
     <file>application.css</file>
     <file>ui/window.ui</file>
     <file>ui/row.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">icons/skip-back-symbolic.svg</file>
+    <file compressed="true" preprocess="xml-stripblanks">icons/skip-forward-symbolic.svg</file>
   </gresource>
-</gresources>
-
+</gresources>
\ No newline at end of file
diff --git a/data/ui/row.ui b/data/ui/row.ui
index 7912ac1..624260f 100644
--- a/data/ui/row.ui
+++ b/data/ui/row.ui
@@ -22,61 +22,6 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="no_show_all">True</property>
-                <child>
-                  <object class="GtkStack" id="playbackStack">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_left">12</property>
-                    <property name="margin_start">12</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="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="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>
@@ -91,9 +36,6 @@
                         <property name="halign">end</property>
                         <property name="margin_left">12</property>
                         <property name="margin_right">12</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -114,6 +56,9 @@
                             <property name="ellipsize">end</property>
                             <property name="single_line_mode">True</property>
                             <property name="xalign">0</property>
+                            <style>
+                              <class name="title"/>
+                            </style>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -125,6 +70,7 @@
                           <object class="GtkLabel" id="date">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
+                            <property name="margin_top">4</property>
                             <property name="xalign">0</property>
                             <style>
                               <class name="subtitle"/>
@@ -185,18 +131,6 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkSeparator">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_bottom">12</property>
-                  </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>
@@ -206,18 +140,26 @@
                     <property name="margin_bottom">12</property>
                     <child>
                       <object class="GtkButton" id="deleteBtn">
-                        <property name="label" translatable="yes">Delete</property>
                         <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>
+                        <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>
                         <style>
-                          <class name="destructive-action"/>
+                          <class name="pill-button"/>
                         </style>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
-                        <property name="pack_type">end</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
@@ -225,13 +167,25 @@
                       <object class="GtkStack" id="renameStack">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="margin_right">12</property>
+                        <property name="hhomogeneous">False</property>
                         <child>
                           <object class="GtkButton" id="renameBtn">
-                            <property name="label" translatable="yes">Rename</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Rename</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</property>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">document-edit-symbolic</property>
+                              </object>
+                            </child>
+                            <style>
+                              <class name="pill-button"/>
+                            </style>
                           </object>
                           <packing>
                             <property name="name">rename</property>
@@ -239,13 +193,24 @@
                         </child>
                         <child>
                           <object class="GtkButton" id="saveBtn">
-                            <property name="label" translatable="yes">Save</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="can_default">True</property>
                             <property name="receives_default">False</property>
+                            <property name="tooltip_text" translatable="yes">Save</property>
                             <property name="valign">center</property>
                             <signal name="clicked" handler="onSaveRecording" swapped="no"/>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">emblem-ok-symbolic</property>
+                              </object>
+                            </child>
+                            <style>
+                              <class name="suggested-action"/>
+                              <class name="pill-button"/>
+                            </style>
                           </object>
                           <packing>
                             <property name="name">save</property>
@@ -260,6 +225,145 @@
                         <property name="position">1</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">center</property>
+                        <property name="valign">center</property>
+                        <property name="hexpand">True</property>
+                        <property name="spacing">18</property>
+                        <child>
+                          <object class="GtkButton" id="seekBackward">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Seek 10s Backward</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</property>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">skip-back-symbolic</property>
+                              </object>
+                            </child>
+                            <style>
+                              <class name="pill-button"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkStack" id="playbackStack">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</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="tooltip_text" translatable="yes">Play</property>
+                                <property name="halign">center</property>
+                                <property name="valign">center</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="margin_left">4</property>
+                                    <property name="margin_right">4</property>
+                                    <property name="margin_top">7</property>
+                                    <property name="margin_bottom">7</property>
+                                    <property name="icon_name">media-playback-start-symbolic</property>
+                                    <property name="icon_size">3</property>
+                                  </object>
+                                </child>
+                                <style>
+                                  <class name="pill-button"/>
+                                </style>
+                              </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="tooltip_text" translatable="yes">Pause</property>
+                                <property name="halign">center</property>
+                                <property name="valign">center</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="margin_left">4</property>
+                                    <property name="margin_right">4</property>
+                                    <property name="margin_top">7</property>
+                                    <property name="margin_bottom">7</property>
+                                    <property name="icon_name">media-playback-pause-symbolic</property>
+                                    <property name="icon_size">3</property>
+                                  </object>
+                                </child>
+                                <style>
+                                  <class name="pill-button"/>
+                                </style>
+                              </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">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="seekForward">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Seek 10s Forward</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</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">skip-forward-symbolic</property>
+                              </object>
+                            </child>
+                            <style>
+                              <class name="pill-button"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 6cdfea6..12b7d7d 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -196,6 +196,7 @@
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">True</property>
+                                <property name="tooltip_text" translatable="yes">Resume Recording</property>
                                 <property name="halign">center</property>
                                 <property name="always_show_image">True</property>
                                 <signal name="clicked" handler="onRecorderResume" swapped="no"/>
@@ -219,6 +220,7 @@
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">True</property>
+                                <property name="tooltip_text" translatable="yes">Pause Recording</property>
                                 <property name="halign">center</property>
                                 <property name="always_show_image">True</property>
                                 <signal name="clicked" handler="onRecorderPause" swapped="no"/>
@@ -250,6 +252,7 @@
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Stop Recording</property>
                             <property name="halign">center</property>
                             <property name="valign">center</property>
                             <signal name="clicked" handler="onRecorderStop" swapped="no"/>
@@ -278,6 +281,7 @@
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Cancel Recording</property>
                             <property name="halign">center</property>
                             <property name="valign">center</property>
                             <property name="always_show_image">True</property>
diff --git a/src/application.js b/src/application.js
index f0e5e41..bab5b6d 100644
--- a/src/application.js
+++ b/src/application.js
@@ -128,6 +128,7 @@ var Application = GObject.registerClass(class Application extends Gtk.Applicatio
         super.vfunc_startup();
 
         this._loadStyleSheet();
+        Gtk.IconTheme.get_default().add_resource_path('/org/gnome/SoundRecorder/icons/');
         log(_('Sound Recorder started'));
         Handy.init();
         Gst.init(null);
diff --git a/src/player.js b/src/player.js
index 5ba697e..8152869 100644
--- a/src/player.js
+++ b/src/player.js
@@ -17,14 +17,33 @@
  * Author: Meg Ford <megford gnome org>
  *
  */
-const { Gio, Gst, Gtk } = imports.gi;
+const { Gio, GObject, Gst, Gtk, GLib } = imports.gi;
 
-
-var Player = class Player {
-    constructor() {
+var Player = new GObject.registerClass({
+    Properties: {
+        'duration': GObject.ParamSpec.int(
+            'duration',
+            'Recording Duration', 'Recording duration in seconds',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+            0, GLib.MAXINT16, 0),
+        'position': GObject.ParamSpec.int(
+            'position',
+            'Player playback position', 'Recording playback position',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+            0, GLib.MAXINT16, 0),
+        'state': GObject.ParamSpec.enum(
+            'state',
+            'Player playback state', 'Recording playback state',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+            Gst.State,
+            Gst.State.NULL),
+    },
+}, class Player extends GObject.Object {
+    _init() {
         this.player = Gst.ElementFactory.make('playbin', 'play');
         let sink = Gst.ElementFactory.make('pulsesink', 'sink');
         this.player.set_property('audio-sink', sink);
+        super._init({});
 
         this.playerBus = this.player.get_bus();
         this.playerBus.connect('message', (playerBus, message) => {
@@ -34,18 +53,18 @@ var Player = class Player {
     }
 
     play(uri) {
-        this.player.set_state(Gst.State.NULL);
+        this.stop();
         this.playerBus.add_signal_watch();
         this.player.set_property('uri', uri);
-        this.player.set_state(Gst.State.PLAYING);
+        this.state = Gst.State.PLAYING;
     }
 
     pause() {
-        this.player.set_state(Gst.State.PAUSED);
+        this.state = Gst.State.PAUSED;
     }
 
     stop() {
-        this.player.set_state(Gst.State.NULL);
+        this.state = Gst.State.NULL;
         this.playerBus.remove_watch();
     }
 
@@ -74,4 +93,29 @@ var Player = class Player {
         errorDialog.connect('response', () => errorDialog.destroy());
         errorDialog.show();
     }
-};
+
+    get duration() {
+        const duration = this.player.query_duration(Gst.Format.TIME)[1];
+        return duration >= 0 ? duration : 0;
+    }
+
+    set position(value) {
+        this._position = value >= 0 ? value : 0;
+        this.player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, this._position);
+        this.notify('position');
+    }
+
+    get position() {
+        return this.player.query_position(Gst.Format.TIME)[1];
+    }
+
+    set state(value) {
+        this._state = value;
+        this.player.set_state(value);
+        this.notify('state');
+    }
+
+    get state() {
+        return this._state;
+    }
+});
diff --git a/src/recording.js b/src/recording.js
index bad742a..05b8117 100644
--- a/src/recording.js
+++ b/src/recording.js
@@ -1,5 +1,5 @@
 /* exported Recording */
-const { GLib, GObject, Gst, GstPbutils } = imports.gi;
+const { GLib, GObject, GstPbutils } = imports.gi;
 
 var Recording = new GObject.registerClass({
     Properties: {
@@ -29,7 +29,7 @@ var Recording = new GObject.registerClass({
         var discoverer = new GstPbutils.Discoverer();
         discoverer.start();
         discoverer.connect('discovered', (_discoverer, audioInfo) => {
-            this._duration = audioInfo.get_duration()  / Gst.SECOND;
+            this._duration = audioInfo.get_duration();
             this.notify('duration');
         });
 
diff --git a/src/recordingsListBox.js b/src/recordingsListBox.js
index a22fc70..e4638db 100644
--- a/src/recordingsListBox.js
+++ b/src/recordingsListBox.js
@@ -1,9 +1,10 @@
 /* exported RecordingsListBox */
-const { GObject, Gtk } = imports.gi;
+const { GObject, Gtk, Gst } = imports.gi;
 const { Row, RowState } = imports.row;
 
 var RecordingsListBox = new GObject.registerClass(class RecordingsListBox extends Gtk.ListBox {
     _init(model, player) {
+        this._player = player;
         super._init({
             valign: Gtk.Align.FILL,
             margin_left: 8,
@@ -15,18 +16,31 @@ var RecordingsListBox = new GObject.registerClass(class RecordingsListBox extend
 
         this.get_style_context().add_class('preferences');
 
+        this._player.connect('notify::state', _player => {
+            if (_player.state === Gst.State.NULL && this.activePlayingRow)
+                this.activePlayingRow.state = RowState.PAUSED;
+        });
+
         this.bind_model(model, recording => {
             let row = new Row(recording);
-
             row.connect('play', _row => {
                 if (this.activePlayingRow && this.activePlayingRow !== _row)
-                    this.activePlayingRow.setState(RowState.PAUSED);
+                    this.activePlayingRow.state = RowState.PAUSED;
 
                 player.play(recording.uri);
                 this.activePlayingRow = _row;
             });
 
-            row.connect('pause', () => player.pause());
+            row.connect('pause', _row => {
+                this._player.pause();
+            });
+
+            row.connect('seek-backward', _ => {
+                player.position -= 10 * Gst.SECOND;
+            });
+            row.connect('seek-forward', _ => {
+                player.position += 10 * Gst.SECOND;
+            });
 
             row.connect('deleted', () => {
                 if (row === this.activeRow)
diff --git a/src/row.js b/src/row.js
index e329d17..0319ab8 100644
--- a/src/row.js
+++ b/src/row.js
@@ -1,5 +1,5 @@
-/* exported Row RowState */
-const { Gdk, GObject, Gtk } = imports.gi;
+/* exported Row */
+const { Gdk, GObject, Gst, Gtk } = imports.gi;
 const { displayDateTime, formatTime } = imports.utils;
 
 var RowState = {
@@ -9,10 +9,12 @@ var RowState = {
 
 var Row = GObject.registerClass({
     Template: 'resource:///org/gnome/SoundRecorder/ui/row.ui',
-    InternalChildren: ['playbackStack', 'mainStack', 'playButton', 'pauseButton', 'name', 'entry', 'date', 
'duration', 'saveBtn', 'revealer', 'renameStack', 'renameBtn', 'deleteBtn'],
+    InternalChildren: ['playbackStack', 'mainStack', 'playButton', 'pauseButton', 'name', 'entry', 'date', 
'duration', 'saveBtn', 'revealer', 'seekBackward', 'seekForward', 'renameStack', 'renameBtn', 'deleteBtn'],
     Signals: {
         'play': { param_types: [GObject.TYPE_STRING] },
         'pause': {},
+        'seek-backward': {},
+        'seek-forward': {},
         'deleted': {},
     },
     Properties: {
@@ -24,9 +26,9 @@ var Row = GObject.registerClass({
     },
 }, class Row extends Gtk.ListBoxRow {
     _init(recording) {
-        super._init({});
         this._recording = recording;
         this._expanded = false;
+        super._init({});
 
         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);
@@ -48,19 +50,22 @@ var Row = GObject.registerClass({
             this._date.label = displayDateTime(recording.timeModified);
 
         recording.connect('notify::duration', () => {
-            this._duration.label = formatTime(recording.duration);
+            this._duration.label = formatTime(recording.duration / Gst.SECOND);
         });
 
         this._playButton.connect('clicked', () => {
-            this.setState(RowState.PLAYING);
             this.emit('play', recording.uri);
+            this.state = RowState.PLAYING;
         });
 
         this._pauseButton.connect('clicked', () => {
-            this.setState(RowState.PAUSED);
             this.emit('pause');
+            this.state = RowState.PAUSED;
         });
 
+        this._seekBackward.connect('clicked', _ => this.emit('seek-backward'));
+        this._seekForward.connect('clicked', _ => this.emit('seek-forward'));
+
         this._renameBtn.connect('clicked', () => {
             this.editMode = true;
         });
@@ -83,13 +88,6 @@ var Row = GObject.registerClass({
         }
     }
 
-    setState(rowState) {
-        if (rowState === RowState.PLAYING)
-            this._playbackStack.visible_child_name = 'pause';
-        else if (rowState === RowState.PAUSED)
-            this._playbackStack.visible_child_name = 'play';
-    }
-
     set editMode(state) {
         this._mainStack.visible_child_name = state ? 'edit' : 'display';
         this._editMode = state;
@@ -118,4 +116,21 @@ var Row = GObject.registerClass({
     get expanded() {
         return this._expanded;
     }
+
+    set state(rowState) {
+        this._state = rowState;
+
+        switch (rowState) {
+        case RowState.PLAYING:
+            this._playbackStack.visible_child_name = 'pause';
+            break;
+        case RowState.PAUSED:
+            this._playbackStack.visible_child_name = 'play';
+            break;
+        }
+    }
+
+    get state() {
+        return this._state;
+    }
 });



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