[the-board] [things] Add voice recording support to SoundThing



commit d5b367b01d0d3526f821cf022fa7861f08b81398
Author: Lucas Rocha <lucasr gnome org>
Date:   Thu Jan 6 21:29:39 2011 +0000

    [things] Add voice recording support to SoundThing

 data/things/Makefile.am                        |    2 +
 data/things/sound/caption-border-recording.png |  Bin 0 -> 251 bytes
 data/things/sound/stop-border.png              |  Bin 0 -> 634 bytes
 data/things/sound/style.css                    |   17 +++
 src/js/ui/things/sound.js                      |  164 +++++++++++++++++++++++-
 5 files changed, 178 insertions(+), 5 deletions(-)
---
diff --git a/data/things/Makefile.am b/data/things/Makefile.am
index 9d7b763..d923681 100644
--- a/data/things/Makefile.am
+++ b/data/things/Makefile.am
@@ -23,11 +23,13 @@ sounddir = $(thingsdir)/sound
 
 dist_sound_DATA = \
     sound/caption-border.png \
+    sound/caption-border-recording.png \
     sound/cassete.png \
     sound/cassete-spool.png \
     sound/sound-controls-bg.png \
     sound/sound-progress-bar-bar.png \
     sound/sound-progress-bar-bg.png \
+    sound/stop-border.png \
     sound/style.css
 
 videodir = $(thingsdir)/video
diff --git a/data/things/sound/caption-border-recording.png b/data/things/sound/caption-border-recording.png
new file mode 100644
index 0000000..afedf53
Binary files /dev/null and b/data/things/sound/caption-border-recording.png differ
diff --git a/data/things/sound/stop-border.png b/data/things/sound/stop-border.png
new file mode 100644
index 0000000..bdcadbc
Binary files /dev/null and b/data/things/sound/stop-border.png differ
diff --git a/data/things/sound/style.css b/data/things/sound/style.css
index 89b2704..081c416 100644
--- a/data/things/sound/style.css
+++ b/data/things/sound/style.css
@@ -31,6 +31,15 @@ MxButton#sound-thing-play-button:checked {
     -mx-icon-name: pause;
 }
 
+MxButton#sound-thing-stop-button {
+    background-color: none;
+    border-image: url('stop-border.png') 4 4 4 4;
+    padding: 7px 14px 3px 14px;
+    font-family: "Action Man";
+    font-size: 16;
+    color: white;
+}
+
 TbBox#sound-thing-sound-border-box {
     border-image: none;
     background-color: none;
@@ -38,6 +47,14 @@ TbBox#sound-thing-sound-border-box {
 
 TbBox#sound-thing-caption-box {
     border-image: url('caption-border.png') 4 4 4 4;
+}
+
+TbBox#sound-thing-caption-box-recording {
+    border-image: url('caption-border-recording.png') 4 4 4 4;
+}
+
+TbBox#sound-thing-caption-box,
+TbBox#sound-thing-caption-box-recording {
     padding: 8px 5px 3px 5px;
 }
 
diff --git a/src/js/ui/things/sound.js b/src/js/ui/things/sound.js
index dc3c37c..7de7893 100644
--- a/src/js/ui/things/sound.js
+++ b/src/js/ui/things/sound.js
@@ -7,6 +7,7 @@ const Tweener = imports.tweener.tweener;
 // gi imports
 const Tb = imports.gi.Tb;
 const Clutter = imports.gi.Clutter;
+const GIO = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
 const Mx = imports.gi.Mx;
@@ -30,6 +31,9 @@ const _CASSETE_IMAGE = Path.THINGS_DATA_DIR + "sound/cassete.png";
 
 const _SHOW_BUTTON_BOX_TIME = 0.5;
 
+const _CAPTION_BOX_STYLE_NORMAL    = "sound-thing-caption-box";
+const _CAPTION_BOX_STYLE_RECORDING = "sound-thing-caption-box-recording";
+
 function SoundThing(args) {
     this._init(args);
 }
@@ -43,6 +47,11 @@ SoundThing.prototype = {
         args.content = this;
         args.canResize = false;
 
+        // Storing voice messages in the music directory for now as, apparently,
+        // there's no standard location for sound files
+        let musicDir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_MUSIC);
+        this._targetVoicePath = musicDir + "/The Board/";
+
         this._style = new Mx.Style();
         this._style.load_from_file(STYLE);
 
@@ -190,7 +199,7 @@ SoundThing.prototype = {
             new Tb.Box({ orientation: Tb.BoxOrientation.HORIZONTAL,
                          xAlign: Tb.BoxAlignment.FILL,
                          yAlign: Tb.BoxAlignment.FILL,
-                         name: "sound-thing-caption-box" });
+                         name: _CAPTION_BOX_STYLE_NORMAL });
 
         this._captionBox.set_style(this._style);
 
@@ -256,6 +265,8 @@ SoundThing.prototype = {
             return;
         }
 
+        this._maybeDeleteVoiceFile();
+
         this._soundFilename = soundFilename;
 
         if (this._soundFilename) {
@@ -332,6 +343,131 @@ SoundThing.prototype = {
                                   false /* not from state*/);
     },
 
+    _ensureTargetVoiceDir : function() {
+        try {
+            let targetDir = GIO.file_new_for_path(this._targetVoicePath);
+
+            // FIXME: we should not be creating this directory
+            // synchronously
+            targetDir.make_directory_with_parents(null);
+        } catch(e) {
+        }
+    },
+
+    _generateVoiceFilename : function() {
+        this._ensureTargetVoiceDir();
+
+        let now = new Date();
+
+        let filename = "VoiceMessage-" +
+                       now.getFullYear() + "-" +
+                       (now.getMonth() + 1) + "-" +
+                       now.getDate() + "-" +
+                       now.getHours() +
+                       now.getMinutes() +
+                       now.getSeconds() +
+                       now.getMilliseconds() +
+                       ".wav";
+
+        return this._targetVoicePath + filename;
+    },
+
+    _startVoiceRecording : function() {
+        if (this._recorder) {
+            return;
+        }
+
+        let filename = this._generateVoiceFilename();
+
+        if (!filename) {
+            return;
+        }
+
+        this._recorder =
+            new Tb.SoundRecorder({ filename: filename });
+
+        this._stopButton =
+            new Mx.Button({ label: Gettext.gettext("Stop"),
+                            name: "sound-thing-stop-button" });
+
+        this._stopButton.connect("clicked",
+                                 Lang.bind(this,
+                                           this._onStopButtonClicked));
+
+        this._stopButton.set_style(this._style);
+
+        this._contentBox.append(this._stopButton,
+                                Tb.BoxPackFlags.FIXED);
+
+        this._contentBox.set_fixed_child_align(this._stopButton,
+                                               Tb.BoxAlignment.CENTER,
+                                               Tb.BoxAlignment.END);
+
+        this._recorder.start();
+
+        this._setSpoolsAnimating(true);
+
+        this._captionBox.name = _CAPTION_BOX_STYLE_RECORDING;
+
+        this._stopEditingCaption();
+        this._textBeforeRecording = this._captionLabel.text;
+        this._captionLabel.text = Gettext.gettext("Recording");
+
+        this._updateControlsVisibility();
+    },
+
+    _stopVoiceRecording : function() {
+        if (!this._recorder) {
+            return;
+        }
+
+        this._setSpoolsAnimating(false);
+
+        let soundFilename = this._recorder.filename;
+
+        this._recorder.stop();
+        delete this._recorder;
+
+        this._stopButton.destroy();
+        delete this._stopButton;
+
+        this._captionBox.name = _CAPTION_BOX_STYLE_NORMAL;
+
+        this._captionLabel.text = this._textBeforeRecording;
+        delete this._textBeforeRecording;
+
+        this._updateSoundFilename(soundFilename,
+                                  true /* avoid autoplaying */);
+
+        this._updateControlsVisibility();
+    },
+
+    _startEditingCaption : function() {
+        this._captionLabel.clutterText.editable = true;
+        this._captionLabel.clutterText.grab_key_focus();
+    },
+
+    _stopEditingCaption : function() {
+        this._captionLabel.clutterText.editable = false;
+    },
+
+    _maybeDeleteVoiceFile : function() {
+        if (!this._soundFilename) {
+            return;
+        }
+
+        let targetDir = GIO.file_new_for_path(this._targetVoicePath);
+
+        let soundFile = GIO.file_new_for_path(this._soundFilename);
+        let parentDir = soundFile.get_parent();
+
+        if (targetDir.equal(parentDir)) {
+            Tb.g_file_delete_async(soundFile, null,
+                                   function() {},
+                                   null);
+        }
+    },
+
     _updateForSoundLoaded : function() {
         this._updateSpinner();
     },
@@ -364,7 +500,8 @@ SoundThing.prototype = {
     },
 
     _updateControlsVisibility : function() {
-        let visible = this._soundFilename &&
+        let visible = !this._recorder &&
+                      this._soundFilename &&
                       (this.hover || this.active);
 
         if (visible) {
@@ -399,6 +536,10 @@ SoundThing.prototype = {
     },
 
     _onCaptionTextChanged : function() {
+        if (this._recorder) {
+            return;
+        }
+
         this.emit('save');
     },
 
@@ -407,6 +548,11 @@ SoundThing.prototype = {
         this._setSpoolsAnimating(this._playButton.toggled);
     },
 
+    _onStopButtonClicked : function() {
+        this._stopVoiceRecording();
+        this._startEditingCaption();
+    },
+
     _onProgressBarButtonPressEvent : function(progressBar, event) {
         let [eventX, eventY] = event.get_coords();
 
@@ -451,13 +597,13 @@ SoundThing.prototype = {
     },
 
     activate : function() {
-        this._captionLabel.clutterText.editable = true;
-        this._captionLabel.clutterText.grab_key_focus();
+        this._startEditingCaption();
         this._updateControlsVisibility();
     },
 
     deactivate : function() {
-        this._captionLabel.clutterText.editable = false;
+        this._stopVoiceRecording();
+        this._stopEditingCaption();
         this._updateControlsVisibility();
     },
 
@@ -483,6 +629,8 @@ SoundThing.prototype = {
     doAction : function(actionName, actionArgs) {
         if (actionName == "chooseFile") {
             this._updateSoundWithFileChooser();
+        } else if (actionName == "recordVoice") {
+            this._startVoiceRecording();
         }
     },
 
@@ -501,6 +649,9 @@ SoundThing.prototype = {
     },
 
     destroy : function() {
+        this._maybeDeleteVoiceFile();
+        this._stopVoiceRecording();
+
         if (this._soundBox) {
             this._soundBox.destroy();
             delete this._soundBox;
@@ -544,6 +695,9 @@ function createToolbar(args) {
     toolBox.addButton({ label: Gettext.gettext("File"),
                         actionName: "chooseFile" });
 
+    toolBox.addButton({ label: Gettext.gettext("Mic"),
+                        actionName: "recordVoice" });
+
     toolbar.addToolBox(toolBox);
 
     return toolbar;



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