Adding first code drop
[demorecorder] / src / AudioCaptureMonitor.vala
diff --git a/src/AudioCaptureMonitor.vala b/src/AudioCaptureMonitor.vala
new file mode 100644 (file)
index 0000000..bead983
--- /dev/null
@@ -0,0 +1,238 @@
+/*  Demo Recorder for MAEMO 5
+*   Copyright (C) 2010 Dru Moore <usr@dru-id.co.uk>
+*   This program is free software; you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License version 2,
+*   or (at your option) any later version, as published by the Free
+*   Software Foundation
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details
+*
+*   You should have received a copy of the GNU General Public
+*   License along with this program; if not, write to the
+*   Free Software Foundation, Inc.,
+*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+namespace IdWorks {
+
+public class AudioCaptureMonitor : Gst.Pipeline {
+  //Gst.Pipeline pipeline;
+  //Gst.Element src;
+  //Gst.Element converter;
+  //Gst.Element pregain;
+  //Gst.Element dynamics;
+  //Gst.Element volume;
+  InputBin input;
+  Gst.Element level;
+  Gst.Element monitor;
+  Gst.Element sink_element;
+  uint watch_id;
+  
+  public AudioCaptureMonitor(string name) {
+    this.name = name;
+    construct_pipeline(SettingsStructures.MonitorSettings());
+  }
+  public AudioCaptureMonitor.with_settings(string name, SettingsStructures.MonitorSettings settings) {
+    this.name = name;
+    construct_pipeline(settings);
+  }
+  
+  private void construct_pipeline(SettingsStructures.MonitorSettings settings) {
+    /*
+    this.src = Gst.ElementFactory.make("pulsesrc", "capture");
+    this.src.set_property("device", "source.hw0");
+    this.add(this.src);
+    
+    this.converter = Gst.ElementFactory.make("audioconvert", "converter");
+    this.add(this.converter);
+    
+    this.pregain = Gst.ElementFactory.make("volume", "pregain");
+    this.pregain.set_property("volume", 1);
+    this.add(this.pregain);
+    
+    this.dynamics = Gst.ElementFactory.make("audiodynamic", "dynamics");
+    this.add(this.dynamics);
+    this.dynamics.set_property("mode", "compressor"); // compressor or expander
+    this.dynamics.set_property("characteristics", "hard-knee"); // hard-knee or soft-knee
+    this.dynamics.set_property("threshold", 1.0); // [0, 1]
+    this.dynamics.set_property("ratio", 1.0); // >= 0
+    
+    this.volume = Gst.ElementFactory.make("volume", "volume");
+    this.volume.set_property("volume", 1);
+    this.add(this.volume);
+    */
+    
+    this.input = new InputBin.with_settings("input", settings.input);
+    this.add(this.input);
+    
+    this.level = Gst.ElementFactory.make("level", "level");
+    this.level.set_property("interval", 50 * Time.Nanoseconds.MILLISECOND);
+    this.level.set_property("peak-ttl", 2 * Time.Nanoseconds.SECOND);
+    this.add(this.level);
+    
+    this.monitor = Gst.ElementFactory.make("volume", "monitor");
+    this.monitor.set_property("volume", 1);
+    this.monitor.set_property("mute", true);
+    this.add(this.monitor);
+    
+    this.sink_element = Gst.ElementFactory.make("autoaudiosink", "fakesink");
+    this.add(this.sink_element);
+    
+    this.level.set_property("message", true);
+    
+    this.sink_element.set_property("sync", true);
+    
+    
+    //Gst.Caps caps = Gst.Caps.from_string ("audio/x-raw-int,channels=2");
+    //this.converter.link_filtered(level, caps);
+    /*
+    this.src.link(converter);
+    this.converter.link(pregain);
+    this.pregain.link(dynamics);
+    this.dynamics.link(volume);
+    this.volume.link(level);
+    */
+    this.input.link(level);
+    this.level.link(monitor);
+    this.monitor.link(sink_element);
+    
+    Gst.Bus bus = this.get_bus();
+    
+    watch_id = bus.add_watch(message_handler);
+    
+  }
+  
+  public void set_dynamics(string mode, string characteristics, double threshold, double ratio) {
+    this.input.set_dynamics(mode, characteristics, threshold, ratio);
+    /*
+    this.dynamics.set_property("mode", mode); // compressor or expander
+    this.dynamics.set_property("characteristics", characteristics); // hard-knee or soft-knee
+    this.dynamics.set_property("threshold", threshold); // [0, 1]
+    this.dynamics.set_property("ratio", ratio); // >= 0
+    */
+  }
+  public void set_dynamics_mode(string mode) {
+    this.input.set_dynamics_mode(mode);
+    //this.dynamics.set_property("mode", mode); // compressor or expander
+  }
+  public void set_dynamics_characteristics(string characteristics) {
+    this.input.set_dynamics_characteristics(characteristics);
+    //this.dynamics.set_property("characteristics", characteristics); // hard-knee or soft-knee
+  }
+  public void set_dynamics_threshold(double threshold) {
+    this.input.set_dynamics_threshold(threshold);
+    //this.dynamics.set_property("threshold", threshold); // [0, 1]
+  }
+  public void set_dynamics_ratio(double ratio) {
+    this.input.set_dynamics_ratio(ratio);
+    //this.dynamics.set_property("ratio", ratio); // >= 0
+  }
+  
+  public void set_source(string name) {
+    this.input.set_source(name);
+  }
+  public string get_source() {
+    return this.input.get_source();
+  }
+  
+  public void set_pregain(double val)
+  requires (val >= 0.0 && val <= 10.0) {
+    this.input.set_pregain(val);
+    //this.pregain.set_property("volume", val);
+  }
+  public double get_pregain()
+  ensures (result >= 0.0 && result <= 10.0) {
+    return this.input.get_pregain();
+    /*GLib.Value val = 0;
+    this.pregain.get_property("volume", ref val);
+    return val.get_double();*/
+  }
+  
+  public void set_volume(double val)
+  requires (val >= 0.0 && val <= 10.0) {
+    this.input.set_volume(val);
+    //this.volume.set_property("volume", val);
+  }
+  public double get_volume()
+  ensures (result >= 0.0 && result <= 10.0) {
+    return this.input.get_volume();
+    /*GLib.Value val = 0;
+    this.volume.get_property("volume", ref val);
+    return val.get_double();*/
+  }
+  
+  public void set_mute(bool val) {
+    this.input.set_mute(val);
+    //this.volume.set_property("mute", val);
+  }
+  public bool get_mute() {
+    return this.input.get_mute();
+    /*GLib.Value val = 0;
+    this.volume.get_property("mute", ref val);
+    return val.get_boolean();*/
+  }
+  
+  public void set_monitor_mute(bool val) {
+    this.monitor.set_property("mute", val);
+  }
+  public bool get_monitor_mute() {
+    GLib.Value val = 0;
+    this.monitor.get_property("mute", ref val);
+    return val.get_boolean();
+  }
+  
+  public void play() {
+    this.set_state(Gst.State.PLAYING);
+  }
+  
+  public void pause() {
+    this.set_state(Gst.State.READY);
+  }
+  
+  public void stop() {
+    this.set_state(Gst.State.READY);
+  }
+  
+  public signal void update_level(int channels, int channel, double rms_dB, double peak_dB, double decay_dB, double rms);
+  
+  public bool message_handler(Gst.Bus bus, Gst.Message message) {
+    if (Gst.MessageType.ELEMENT == message.type) {
+      Gst.Structure s = message.get_structure();
+      string name = s.get_name();
+      
+      if ("level" == name) {
+        int channels;
+        double rms_dB, peak_dB, decay_dB;
+        double rms;
+        Gst.Value list;
+        Gst.Value value;
+        int i;
+              
+        list = s.get_value("rms"); // any value gives us the channelsby list size
+        channels = 0;
+        channels = (int) list.list_get_size();
+        
+        for (i = 0; i < channels; ++i) {          
+          list = s.get_value ("rms");
+          value = list.list_get_value (i);
+          rms_dB = value.get_double ();
+          list = s.get_value ("peak");
+          value = list.list_get_value (i);
+          peak_dB = value.get_double ();
+          list = s.get_value ("decay");
+          value = list.list_get_value (i);
+          decay_dB = value.get_double ();
+          /* converting from dB to normal gives us a value between 0.0 and 1.0 */
+          rms = Math.pow (10, rms_dB / 20);
+          update_level(channels, i, rms_dB, peak_dB, decay_dB, rms);
+        }
+      }
+    }
+    return true;
+  }
+
+}
+
+}
\ No newline at end of file