Reworked track settings.
[demorecorder] / src / AcmPopUp.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 AcmPopUp : Hildon.Dialog {
21     
22     SettingsStructures.MonitorSettings settings;
23     AudioCaptureMonitor acm;
24     Gtk.Label lbl_level_1;
25     Gtk.Label lbl_level_2;
26     Gtk.HScale pregain_slider;
27     Gtk.HScale volume_slider;
28     Hildon.Button dynamics_settings_btn;
29     Hildon.CheckButton dynamics_btn;
30     Hildon.TouchSelector source_selector;
31     DbMonitorWidget monitor_1;
32     DbMonitorWidget monitor_2;
33     const string level_format = "%02.1f/%02.1fdB";
34     
35     public AcmPopUp(string title, Gtk.Widget parent) {
36       this.set_title(title);
37       this.set_parent(parent);
38       this.settings = SettingsStructures.MonitorSettings();
39       this.construct_interface();
40       update_settings();
41     }
42     public AcmPopUp.with_settings(string title, Gtk.Widget parent, SettingsStructures.MonitorSettings settings) {
43       this.set_title(title);
44       this.set_parent(parent);
45       this.settings = settings;
46       this.construct_interface();
47       update_settings();
48     }
49     
50     public void set_settings_structure(SettingsStructures.MonitorSettings settings) {
51       this.settings = settings;
52       update_settings();
53     }
54     public SettingsStructures.MonitorSettings get_settings_structure() {
55       return this.settings;
56     }
57     
58     private void update_settings() {
59       set_volume(settings.input.volume);
60       set_pregain(settings.input.pregain);
61       //set_source(settings.input.source);
62       dynamics_btn.set_active(settings.input.dynamics.active);
63       toggle_dynamics(settings.input.dynamics.active);
64     }
65     
66     private void set_volume(double val) {
67       volume_slider.set_value(val);
68       settings.input.volume = val;
69       if (null != acm) acm.set_volume(val);
70     }
71     private void set_pregain(double val) {
72       pregain_slider.set_value(val);
73       settings.input.pregain = val;
74       if (null != acm) acm.set_pregain(val);
75     }
76     
77     private void set_source(string name) {
78       switch (name) {
79         case "Microphone":
80           source_selector.set_active(0, 0);
81           break;
82         case "Monitor":
83           source_selector.set_active(0, 1);
84           break;
85         case "Bluetooth":
86           source_selector.set_active(0, 2);
87           break;
88         default:
89           source_selector.set_active(0, 0);
90           break;
91       }
92       settings.input.source = name;
93       if (null != acm) acm.set_source(name);
94     }
95     private void set_input_source(string name) {
96       settings.input.source = name;
97       if (null != acm) acm.set_source(name);
98     }
99     
100     private void construct_interface() {
101       this.set_default_response(Gtk.ResponseType.CANCEL);
102       this.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK);
103       this.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
104       
105       Gtk.VBox control_area = (Gtk.VBox)this.get_content_area();
106       
107       acm = new AudioCaptureMonitor("Recorder");
108       acm.update_level.connect(update_level_callback);
109       
110       Gtk.HButtonBox input_bar = new Gtk.HButtonBox();
111       input_bar.set_layout(Gtk.ButtonBoxStyle.START);
112       input_bar.set_homogeneous(true);
113       input_bar.set_spacing(2);
114       
115       source_selector = new Hildon.TouchSelector.text();
116       source_selector.append_text("Microphone");
117       source_selector.append_text("Monitor");
118       source_selector.append_text("Bluetooth");
119       //source_selector.set_active(0, 0);
120       this.set_source(settings.input.source);
121       Hildon.PickerButton source_picker = new Hildon.PickerButton(Hildon.SizeType.FINGER_HEIGHT | Hildon.SizeType.AUTO_WIDTH, Hildon.ButtonArrangement.VERTICAL);
122       source_picker.set_title("Source:");
123       source_picker.set_selector(source_selector);
124       source_picker.set_alignment(0, 0, 1, 1);
125       source_picker.set_image(new Gtk.Image.from_icon_name("camera_volume_unmuted", Gtk.IconSize.BUTTON));
126       source_picker.value_changed.connect( (s) => { set_input_source(s.get_selector().get_current_text()); } );
127       input_bar.pack_start(source_picker, true, true, 2);
128       
129       Hildon.CheckButton audio_btn = new Hildon.CheckButton(Hildon.SizeType.FINGER_HEIGHT | Hildon.SizeType.AUTO_WIDTH);
130       audio_btn.set_label("Enable monitor");
131       //audio_btn.set_image(new Gtk.Image.from_icon_name("statusarea_volume_headset", Gtk.IconSize.BUTTON));
132       audio_btn.toggled.connect( (s) => {toggle_monitor(s.get_active());} );
133       input_bar.pack_start(audio_btn, true, false, 2);
134       
135       control_area.pack_start(input_bar, true, true, 4);
136       
137       Gtk.HBox monitor_1_bar = new Gtk.HBox(false, 2);
138       lbl_level_1 = new Gtk.Label(level_format.printf(0, 0));
139       monitor_1 = new DbMonitorWidget();
140       monitor_1.set_layout(DbMonitorWidget.Layout.HORIZONTAL);
141       monitor_1.set_peak(1);
142       monitor_1.set_decay(1.5);
143       monitor_1_bar.pack_start(new Gtk.Label("L"), false, false, 2);
144       monitor_1_bar.pack_start(monitor_1, true, true, 2);
145       monitor_1_bar.pack_start(lbl_level_1, false, false, 2);
146       control_area.pack_start(monitor_1_bar, true, true, 2);
147       
148       Gtk.HBox monitor_2_bar = new Gtk.HBox(false, 4);
149       lbl_level_2 = new Gtk.Label(level_format.printf(0, 0));
150       monitor_2 = new DbMonitorWidget();
151       monitor_2.set_layout(DbMonitorWidget.Layout.HORIZONTAL);
152       monitor_2.set_peak(1);
153       monitor_2.set_decay(1.5);
154       monitor_2_bar.pack_start(new Gtk.Label("R"), false, false, 2);
155       monitor_2_bar.pack_start(monitor_2, true, true, 2);
156       monitor_2_bar.pack_start(lbl_level_2, false, false, 2);
157       control_area.pack_start(monitor_2_bar, true, true, 2);
158       
159       Gtk.HBox pregain_bar = new Gtk.HBox(false, 4);
160       Gtk.Label pregain_label = new Gtk.Label("Pre-gain");
161       pregain_bar.pack_start(pregain_label, false, false , 2);
162       pregain_slider = new Gtk.HScale.with_range(0.0, 10.0, 0.1);
163       pregain_slider.set_value_pos(Gtk.PositionType.LEFT);
164       pregain_slider.value_changed.connect((s) => {this.set_pregain(s.get_value());});
165       pregain_bar.pack_start(pregain_slider, true, true , 2);
166       
167       control_area.pack_start(pregain_bar, true, true , 2);
168       
169       Gtk.HBox dynamics_bar = new Gtk.HBox(false, 4);
170       dynamics_btn = new Hildon.CheckButton(Hildon.SizeType.FINGER_HEIGHT | Hildon.SizeType.AUTO_WIDTH);
171       dynamics_btn.set_label("Enable dynamics");
172       dynamics_btn.toggled.connect( (s) => {toggle_dynamics(s.get_active());} );
173       dynamics_bar.pack_start(dynamics_btn, true, false, 2);
174       dynamics_settings_btn = new Hildon.Button(Hildon.SizeType.FINGER_HEIGHT | Hildon.SizeType.AUTO_WIDTH, Hildon.ButtonArrangement.HORIZONTAL);
175       dynamics_settings_btn.set_text("Settings", "");
176       dynamics_settings_btn.set_image(new Gtk.Image.from_icon_name("general_settings", Gtk.IconSize.BUTTON));
177       dynamics_settings_btn.set_image_position(Gtk.PositionType.LEFT);
178       dynamics_settings_btn.clicked.connect(do_dynamics_popup);
179       dynamics_bar.pack_start(dynamics_settings_btn, true, false, 2);
180       
181       control_area.pack_start(dynamics_bar, true, true , 2);
182       
183       Gtk.HBox volume_bar = new Gtk.HBox(false, 4);
184       Gtk.Label volume_label = new Gtk.Label("Volume");
185       volume_bar.pack_start(volume_label, false, false , 2);
186       volume_slider = new Gtk.HScale.with_range(0.0, 10.0, 0.1);
187       volume_slider.set_value_pos(Gtk.PositionType.LEFT);
188       volume_slider.value_changed.connect((s) => {this.set_volume(s.get_value());});
189       volume_bar.pack_start(volume_slider, true, true , 2);
190       
191       control_area.pack_start(volume_bar, true, true , 2);
192       
193       this.update_settings();
194       this.show_all();
195     }
196     
197     public void play() {
198       acm.play();
199     }
200     
201     public void pause() {
202       acm.pause();
203     }
204     
205     public void stop() {
206       acm.stop();
207     }
208     
209     private void toggle_monitor(bool state) {
210       if (null != acm) {
211         acm.set_monitor_mute(!state);
212       }
213     }
214     
215     private void toggle_dynamics(bool state) {
216       this.settings.input.dynamics.active = state;
217       this.dynamics_settings_btn.set_sensitive(state);
218       if (null != acm) {
219         if (!state) {
220           SettingsStructures.DynamicsSettings ds = SettingsStructures.DynamicsSettings();
221           acm.set_dynamics(ds.mode, ds.characteristics, ds.threshold, ds.ratio); // shouldn't be applied
222         }
223         else {
224           acm.set_dynamics(settings.input.dynamics.mode, settings.input.dynamics.characteristics, settings.input.dynamics.threshold, settings.input.dynamics.ratio);
225         }
226       }
227     }
228     
229     private void do_dynamics_popup() {
230       stdout.printf("dynamics popup new called\n");
231       stdout.flush();
232       DynamicsPopUp dlg = new DynamicsPopUp.with_settings("Monitoring dynamics settings", this, settings.input.dynamics);
233       dlg.set_transient_for(this.get_transient_for());
234       dlg.mode_updated.connect(this.dynamics_update_mode_callback);
235       dlg.characteristics_updated.connect(this.dynamics_update_characteristics_callback);
236       dlg.ratio_updated.connect(this.dynamics_update_ratio_callback);
237       dlg.threshold_updated.connect(this.dynamics_update_threshold_callback);
238       stdout.printf("dynamics connections made\n");
239       stdout.flush();
240       dlg.run();
241       stdout.printf("dynamics back from run\n");
242       stdout.flush();
243       dlg.destroy();
244     }
245     private void dynamics_update_mode_callback(DynamicsPopUp sender, string val) {
246       settings.input.dynamics.mode = val;
247       if (null != acm) {
248         acm.set_dynamics_mode(val);
249       }
250     }
251     private void dynamics_update_characteristics_callback(DynamicsPopUp sender, string val) {
252       settings.input.dynamics.characteristics = val;
253       if (null != acm) {
254         acm.set_dynamics_characteristics(val);
255       }
256     }
257     private void dynamics_update_ratio_callback(DynamicsPopUp sender, double val) {
258       settings.input.dynamics.ratio = val;
259       if (null != acm) {
260         acm.set_dynamics_ratio(val);
261       }
262     }
263     private void dynamics_update_threshold_callback(DynamicsPopUp sender, double val) {
264       settings.input.dynamics.threshold = val;
265       if (null != acm) {
266         acm.set_dynamics_threshold(val);
267       }
268     }
269     
270     private void update_level_callback(AudioCaptureMonitor sender, int channels, int channel, double rms_dB, double peak_dB, double decay_dB, double rms) {
271       //string text = level_format.printf(channel.to_string(), rms_dB, peak_dB, decay_dB, rms, Math.pow (10, decay_dB / 20));
272       string text = level_format.printf(peak_dB, decay_dB);
273       if (0 == channel) {
274         lbl_level_1.set_text(text);
275         monitor_1.set_peak(Math.pow (10, peak_dB / 20));
276         monitor_1.set_decay(Math.pow (10, decay_dB / 20));
277       }
278       else if (1 == channel) {
279         lbl_level_2.set_text(text);
280         monitor_2.set_peak(Math.pow (10, peak_dB / 20));
281         monitor_2.set_decay(Math.pow (10, decay_dB / 20));
282       }
283       else {
284         stdout.printf("channel %s found\n", channel.to_string());
285         stdout.flush();
286       }
287     }
288     
289   }
290   
291 }