Merge branch 'master--optional-external-libs' of https://github.com/nphilipp/ardour
[ardour.git] / gtk2_ardour / time_fx_dialog.cc
1 /*
2     Copyright (C) 2000-2009 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "time_fx_dialog.h"
21
22 #include <iostream>
23 #include <cstdlib>
24 #include <cmath>
25
26 #include <string>
27
28 #include "pbd/error.h"
29 #include "pbd/pthread_utils.h"
30 #include "pbd/memento_command.h"
31
32 #include <gtkmm2ext/utils.h>
33
34 #include "editor.h"
35 #include "audio_time_axis.h"
36 #include "audio_region_view.h"
37 #include "region_selection.h"
38
39 #ifdef USE_RUBBERBAND
40 #include <rubberband/RubberBandStretcher.h>
41 using namespace RubberBand;
42 #endif
43
44 #include "i18n.h"
45
46 using namespace std;
47 using namespace ARDOUR;
48 using namespace PBD;
49 using namespace Gtk;
50 using namespace Gtkmm2ext;
51
52 TimeFXDialog::TimeFXDialog (Editor& e, bool pitch)
53         : ArdourDialog (X_("time fx dialog"))
54         , editor (e)
55         , pitching (pitch)
56         , pitch_octave_adjustment (0.0, -4.0, 4.0, 1, 2.0)
57         , pitch_semitone_adjustment (0.0, -12.0, 12.0, 1.0, 4.0)
58         , pitch_cent_adjustment (0.0, -499.0, 500.0, 5.0, 15.0)
59         , pitch_octave_spinner (pitch_octave_adjustment)
60         , pitch_semitone_spinner (pitch_semitone_adjustment)
61         , pitch_cent_spinner (pitch_cent_adjustment)
62         , quick_button (_("Quick but Ugly"))
63         , antialias_button (_("Skip Anti-aliasing"))
64         , stretch_opts_label (_("Contents:"))
65         , precise_button (_("Minimize time distortion"))
66         , preserve_formants_button(_("Preserve Formants"))
67 {
68         set_modal (true);
69         set_skip_taskbar_hint (true);
70         set_resizable (false);
71         set_name (N_("TimeFXDialog"));
72
73         if (pitching) {
74                 set_title (_("Pitch Shift Audio"));
75         } else {
76                 set_title (_("Time Stretch Audio"));
77         }
78
79         cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
80
81         VBox* vbox = manage (new VBox);
82         Gtk::Label* l;
83
84         get_vbox()->set_spacing (4);
85
86         vbox->set_spacing (18);
87         vbox->set_border_width (5);
88
89         upper_button_box.set_spacing (6);
90
91         l = manage (new Label (_("<b>Options</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false ));
92         l->set_use_markup ();
93
94         upper_button_box.pack_start (*l, false, false);
95
96         if (pitching) {
97                 Table* table = manage (new Table (4, 3, false));
98                 table->set_row_spacings (6);
99                 table->set_col_spacing  (1, 6);
100                 l = manage (new Label ("", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false )); //Common gnome way for padding
101                 l->set_padding (8, 0);
102                 table->attach (*l, 0, 1, 0, 4, Gtk::FILL, Gtk::FILL, 0, 0);
103
104                 l = manage (new Label (_("Octaves:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
105                 table->attach (*l, 1, 2, 0, 1, Gtk::FILL, Gtk::EXPAND, 0, 0);
106                 table->attach (pitch_octave_spinner, 2, 3, 0, 1, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
107                 pitch_octave_spinner.set_activates_default ();
108
109                 l = manage (new Label (_("Semitones:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
110                 table->attach (*l, 1, 2, 1, 2, Gtk::FILL, Gtk::EXPAND, 0, 0);
111                 table->attach (pitch_semitone_spinner, 2, 3, 1, 2, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
112                 pitch_semitone_spinner.set_activates_default ();
113
114                 l = manage (new Label (_("Cents:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
115                 pitch_cent_spinner.set_digits (1);
116                 table->attach (*l, 1, 2, 2, 3, Gtk::FILL, Gtk::EXPAND, 0, 0);
117                 table->attach (pitch_cent_spinner, 2, 3, 2, 3, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
118                 pitch_cent_spinner.set_activates_default ();
119
120                 table->attach (preserve_formants_button, 1, 3, 3, 4, Gtk::FILL, Gtk::EXPAND, 0, 0);
121
122                 add_button (S_("Time|Shift"), Gtk::RESPONSE_ACCEPT);
123
124                 upper_button_box.pack_start (*table, false, true);
125         } else {
126                 Table* table = manage (new Table (2, 3, false));
127                 table->set_row_spacings (6);
128                 table->set_col_spacing  (1, 6);
129                 l = manage (new Label ("", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false ));
130                 l->set_padding (8, 0);
131                 table->attach (*l, 0, 1, 0, 2, Gtk::FILL, Gtk::FILL, 0, 0);
132
133 #ifdef USE_RUBBERBAND
134                 vector<string> strings;
135
136                 table->attach (stretch_opts_label, 1, 2, 0, 1, Gtk::FILL, Gtk::EXPAND, 0, 0);
137
138                 set_popdown_strings (stretch_opts_selector, editor.rb_opt_strings);
139                 /* set default */
140                 stretch_opts_selector.set_active_text (editor.rb_opt_strings[editor.rb_current_opt]);
141                 table->attach (stretch_opts_selector, 2, 3, 0, 1, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
142
143                 table->attach (precise_button, 1, 3, 1, 2, Gtk::FILL, Gtk::EXPAND, 0, 0);
144
145 #else
146                 quick_button.set_name (N_("TimeFXButton"));
147                 table->attach (quick_button, 1, 3, 0, 1, Gtk::FILL, Gtk::EXPAND, 0, 0);
148
149                 antialias_button.set_name (N_("TimeFXButton"));
150                 table->attach (antialias_button, 1, 3, 1, 2, Gtk::FILL, Gtk::EXPAND, 0, 0);
151
152 #endif
153
154                 add_button (_("Stretch/Shrink"), Gtk::RESPONSE_ACCEPT);
155
156                 upper_button_box.pack_start (*table, false, true);
157         }
158
159         set_default_response (Gtk::RESPONSE_ACCEPT);
160         
161         VBox* progress_box = manage (new VBox);
162         progress_box->set_spacing (6);
163
164         l = manage (new Label (_("<b>Progress</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
165         l->set_use_markup ();
166
167         progress_box->pack_start (*l, false, false);
168         progress_box->pack_start (progress_bar, false, true);
169
170
171         vbox->pack_start (upper_button_box, false, true);
172         vbox->pack_start (*progress_box, false, true);
173
174         get_vbox()->pack_start (*vbox, false, false);
175
176         show_all_children ();
177 }
178
179 void
180 TimeFXDialog::update_progress_gui (float p)
181 {
182         progress_bar.set_fraction (p);
183 }
184
185 void
186 TimeFXDialog::cancel_in_progress ()
187 {
188         status = -2;
189         request.cancel = true;
190         first_cancel.disconnect();
191 }
192
193 gint
194 TimeFXDialog::delete_in_progress (GdkEventAny*)
195 {
196         status = -2;
197         request.cancel = true;
198         first_delete.disconnect();
199         return TRUE;
200 }
201