Adding first code drop
[demorecorder] / src / AudioCaptureMonitor.vala
1 /*  Demo Recorder for MAEMO 5
2 *   Copyright (C) 2010 Dru Moore <usr@dru-id.co.uk>
3 *   This program is free software; you can redistribute it and/or modify
4 *   it under the terms of the GNU General Public License version 2,
5 *   or (at your option) any later version, as published by the Free
6 *   Software Foundation
7 *
8 *   This program is distributed in the hope that it will be useful,
9 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *   GNU General Public License for more details
12 *
13 *   You should have received a copy of the GNU General Public
14 *   License along with this program; if not, write to the
15 *   Free Software Foundation, Inc.,
16 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 */
18 namespace IdWorks {
19
20 public class AudioCaptureMonitor : Gst.Pipeline {
21   //Gst.Pipeline pipeline;
22   //Gst.Element src;
23   //Gst.Element converter;
24   //Gst.Element pregain;
25   //Gst.Element dynamics;
26   //Gst.Element volume;
27   InputBin input;
28   Gst.Element level;
29   Gst.Element monitor;
30   Gst.Element sink_element;
31   uint watch_id;
32   
33   public AudioCaptureMonitor(string name) {
34     this.name = name;
35     construct_pipeline(SettingsStructures.MonitorSettings());
36   }
37   public AudioCaptureMonitor.with_settings(string name, SettingsStructures.MonitorSettings settings) {
38     this.name = name;
39     construct_pipeline(settings);
40   }
41   
42   private void construct_pipeline(SettingsStructures.MonitorSettings settings) {
43     /*
44     this.src = Gst.ElementFactory.make("pulsesrc", "capture");
45     this.src.set_property("device", "source.hw0");
46     this.add(this.src);
47     
48     this.converter = Gst.ElementFactory.make("audioconvert", "converter");
49     this.add(this.converter);
50     
51     this.pregain = Gst.ElementFactory.make("volume", "pregain");
52     this.pregain.set_property("volume", 1);
53     this.add(this.pregain);
54     
55     this.dynamics = Gst.ElementFactory.make("audiodynamic", "dynamics");
56     this.add(this.dynamics);
57     this.dynamics.set_property("mode", "compressor"); // compressor or expander
58     this.dynamics.set_property("characteristics", "hard-knee"); // hard-knee or soft-knee
59     this.dynamics.set_property("threshold", 1.0); // [0, 1]
60     this.dynamics.set_property("ratio", 1.0); // >= 0
61     
62     this.volume = Gst.ElementFactory.make("volume", "volume");
63     this.volume.set_property("volume", 1);
64     this.add(this.volume);
65     */
66     
67     this.input = new InputBin.with_settings("input", settings.input);
68     this.add(this.input);
69     
70     this.level = Gst.ElementFactory.make("level", "level");
71     this.level.set_property("interval", 50 * Time.Nanoseconds.MILLISECOND);
72     this.level.set_property("peak-ttl", 2 * Time.Nanoseconds.SECOND);
73     this.add(this.level);
74     
75     this.monitor = Gst.ElementFactory.make("volume", "monitor");
76     this.monitor.set_property("volume", 1);
77     this.monitor.set_property("mute", true);
78     this.add(this.monitor);
79     
80     this.sink_element = Gst.ElementFactory.make("autoaudiosink", "fakesink");
81     this.add(this.sink_element);
82     
83     this.level.set_property("message", true);
84     
85     this.sink_element.set_property("sync", true);
86     
87     
88     //Gst.Caps caps = Gst.Caps.from_string ("audio/x-raw-int,channels=2");
89     //this.converter.link_filtered(level, caps);
90     /*
91     this.src.link(converter);
92     this.converter.link(pregain);
93     this.pregain.link(dynamics);
94     this.dynamics.link(volume);
95     this.volume.link(level);
96     */
97     this.input.link(level);
98     this.level.link(monitor);
99     this.monitor.link(sink_element);
100     
101     Gst.Bus bus = this.get_bus();
102     
103     watch_id = bus.add_watch(message_handler);
104     
105   }
106   
107   public void set_dynamics(string mode, string characteristics, double threshold, double ratio) {
108     this.input.set_dynamics(mode, characteristics, threshold, ratio);
109     /*
110     this.dynamics.set_property("mode", mode); // compressor or expander
111     this.dynamics.set_property("characteristics", characteristics); // hard-knee or soft-knee
112     this.dynamics.set_property("threshold", threshold); // [0, 1]
113     this.dynamics.set_property("ratio", ratio); // >= 0
114     */
115   }
116   public void set_dynamics_mode(string mode) {
117     this.input.set_dynamics_mode(mode);
118     //this.dynamics.set_property("mode", mode); // compressor or expander
119   }
120   public void set_dynamics_characteristics(string characteristics) {
121     this.input.set_dynamics_characteristics(characteristics);
122     //this.dynamics.set_property("characteristics", characteristics); // hard-knee or soft-knee
123   }
124   public void set_dynamics_threshold(double threshold) {
125     this.input.set_dynamics_threshold(threshold);
126     //this.dynamics.set_property("threshold", threshold); // [0, 1]
127   }
128   public void set_dynamics_ratio(double ratio) {
129     this.input.set_dynamics_ratio(ratio);
130     //this.dynamics.set_property("ratio", ratio); // >= 0
131   }
132   
133   public void set_source(string name) {
134     this.input.set_source(name);
135   }
136   public string get_source() {
137     return this.input.get_source();
138   }
139   
140   public void set_pregain(double val)
141   requires (val >= 0.0 && val <= 10.0) {
142     this.input.set_pregain(val);
143     //this.pregain.set_property("volume", val);
144   }
145   public double get_pregain()
146   ensures (result >= 0.0 && result <= 10.0) {
147     return this.input.get_pregain();
148     /*GLib.Value val = 0;
149     this.pregain.get_property("volume", ref val);
150     return val.get_double();*/
151   }
152   
153   public void set_volume(double val)
154   requires (val >= 0.0 && val <= 10.0) {
155     this.input.set_volume(val);
156     //this.volume.set_property("volume", val);
157   }
158   public double get_volume()
159   ensures (result >= 0.0 && result <= 10.0) {
160     return this.input.get_volume();
161     /*GLib.Value val = 0;
162     this.volume.get_property("volume", ref val);
163     return val.get_double();*/
164   }
165   
166   public void set_mute(bool val) {
167     this.input.set_mute(val);
168     //this.volume.set_property("mute", val);
169   }
170   public bool get_mute() {
171     return this.input.get_mute();
172     /*GLib.Value val = 0;
173     this.volume.get_property("mute", ref val);
174     return val.get_boolean();*/
175   }
176   
177   public void set_monitor_mute(bool val) {
178     this.monitor.set_property("mute", val);
179   }
180   public bool get_monitor_mute() {
181     GLib.Value val = 0;
182     this.monitor.get_property("mute", ref val);
183     return val.get_boolean();
184   }
185   
186   public void play() {
187     this.set_state(Gst.State.PLAYING);
188   }
189   
190   public void pause() {
191     this.set_state(Gst.State.READY);
192   }
193   
194   public void stop() {
195     this.set_state(Gst.State.READY);
196   }
197   
198   public signal void update_level(int channels, int channel, double rms_dB, double peak_dB, double decay_dB, double rms);
199   
200   public bool message_handler(Gst.Bus bus, Gst.Message message) {
201     if (Gst.MessageType.ELEMENT == message.type) {
202       Gst.Structure s = message.get_structure();
203       string name = s.get_name();
204       
205       if ("level" == name) {
206         int channels;
207         double rms_dB, peak_dB, decay_dB;
208         double rms;
209         Gst.Value list;
210         Gst.Value value;
211         int i;
212               
213         list = s.get_value("rms"); // any value gives us the channelsby list size
214         channels = 0;
215         channels = (int) list.list_get_size();
216         
217         for (i = 0; i < channels; ++i) {          
218           list = s.get_value ("rms");
219           value = list.list_get_value (i);
220           rms_dB = value.get_double ();
221           list = s.get_value ("peak");
222           value = list.list_get_value (i);
223           peak_dB = value.get_double ();
224           list = s.get_value ("decay");
225           value = list.list_get_value (i);
226           decay_dB = value.get_double ();
227           /* converting from dB to normal gives us a value between 0.0 and 1.0 */
228           rms = Math.pow (10, rms_dB / 20);
229           update_level(channels, i, rms_dB, peak_dB, decay_dB, rms);
230         }
231       }
232     }
233     return true;
234   }
235
236 }
237
238 }