edit group selection and cut/copy/paste/del shortcuts, interview mode tweaks
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / meterpanel.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "clip.h"
23 #include "edl.h"
24 #include "edlsession.h"
25 #include "language.h"
26 #include "meterpanel.h"
27 #include "mwindow.h"
28 #include "preferences.h"
29 #include "theme.h"
30 #include "vframe.h"
31
32
33
34 MeterPanel::MeterPanel(MWindow *mwindow, BC_WindowBase *subwindow,
35         int x, int y, int w, int h, int meter_count,
36         int visible, int use_headroom, int use_titles)
37 {
38         this->subwindow = subwindow;
39         this->mwindow = mwindow;
40         this->x = x;
41         this->y = y;
42         this->w = w;
43         this->h = h;
44         this->meter_count = meter_count;
45         this->visible = visible;
46         this->use_headroom = use_headroom;
47         this->use_titles = use_titles;
48 }
49
50
51 MeterPanel::~MeterPanel()
52 {
53         meters.remove_all_objects();
54         meter_titles.remove_all_objects();
55 }
56
57 void MeterPanel::create_objects()
58 {
59         set_meters(meter_count, visible);
60 }
61
62 int MeterPanel::set_meters(int meter_count, int visible)
63 {
64         if(meter_count != meters.total || visible != this->visible)
65         {
66 // Delete old meters
67                 if(meter_count != meters.total)
68                 {
69                         meters.remove_all_objects();
70                         meter_titles.remove_all_objects();
71                         meter_peaks.remove_all();
72                 }
73
74                 this->meter_count = meter_count;
75                 this->visible = visible;
76 //              if(!visible) this->meter_count = 0;
77
78                 if(meter_count && !meters.size())
79                 {
80                         int x1 = this->x;
81                         int y1 = this->y;
82                         int h1 = get_meter_h();
83                         int border = mwindow->theme->widget_border;
84                         for(int i = 0; i < meter_count; i++)
85                         {
86 //printf("MeterPanel::set_meters %d %d %d %d\n", __LINE__, i, x1, get_meter_w(i));
87                                 y1 = this->y;
88
89                                 if(use_titles)
90                                 {
91                                         BC_Title *new_title;
92                                         subwindow->add_subwindow(new_title = new BC_Title(
93                                                 get_title_x(i, "0"),
94                                                 y1,
95                                                 "0",
96                                                 SMALLFONT));
97                                         y1 += new_title->get_h() + border;
98                                         meter_titles.append(new_title);
99                                 }
100
101                                 MeterMeter *new_meter;
102                                 subwindow->add_subwindow(new_meter = new MeterMeter(mwindow,
103                                         this,
104                                         x1,
105                                         y1,
106                                         this->w > 0 ? get_meter_w(i) : -1,
107                                         h1,
108                                         (i == 0)));
109                                 meters.append(new_meter);
110                         x1 += get_meter_w(i) + border;
111
112                                 meter_peaks.append(0);
113                         }
114                 }
115         }
116
117         return 0;
118 }
119
120 void MeterPanel::reposition_window(int x, int y, int w, int h)
121 {
122         this->x = x;
123         this->y = y;
124         this->w = w;
125         this->h = h;
126
127 //printf("MeterPanel::reposition_window 0 %d\n", meter_count);
128
129         int border = mwindow->theme->widget_border;
130         int x1 = x;
131         for(int i = 0; i < meter_count; i++)
132         {
133                 if(use_titles)
134                 {
135                         meter_titles.get(i)->reposition_window(
136                                 get_title_x(i, meter_titles.get(i)->get_text()),
137                                 meter_titles.get(i)->get_y());
138                 }
139 //printf("MeterPanel::reposition_window %d %d %d %d\n", __LINE__, i, x1, get_meter_w(i));
140                 meters.get(i)->reposition_window(x1,
141                         meters.get(i)->get_y(),
142                         get_meter_w(i),
143                         get_meter_h());
144                 x1 += get_meter_w(i) + border;
145         }
146 }
147
148 int MeterPanel::change_status_event(int new_status)
149 {
150 //printf("MeterPanel::change_status_event\n");
151         return 1;
152 }
153
154 int MeterPanel::get_reset_x()
155 {
156         return x +
157                 get_meters_width(mwindow->theme, meter_count, visible) -
158                 mwindow->theme->over_button[0]->get_w();
159 }
160
161 int MeterPanel::get_reset_y()
162 {
163         return y + h - mwindow->theme->over_button[0]->get_h();
164 }
165
166 int MeterPanel::get_title_x(int number, const char *text)
167 {
168         int border = mwindow->theme->widget_border;
169         int x1 = x;
170
171         for(int i = 0; i < meter_count; i++)
172         {
173                 if(i == number)
174                 {
175                         int text_w = subwindow->get_text_width(SMALLFONT, text);
176                         int title_x = x1;
177                         int meter_w = (i == 0) ?
178                                 get_meter_w(i) - BC_Meter::get_title_w() :
179                                 get_meter_w(i);
180                         title_x += (i == 0) ? BC_Meter::get_title_w() : 0;
181                         title_x += meter_w / 2 -
182                                 text_w / 2;
183                         title_x = MAX(title_x, x1);
184                         if(i == 0) title_x = MAX(title_x, x1 + BC_Meter::get_title_w());
185                         return title_x;
186                 }
187
188
189                 x1 += get_meter_w(i) + border;
190         }
191         return -1;
192 }
193
194 int MeterPanel::get_meters_width(Theme *theme, int meter_count, int visible)
195 {
196 //printf("MeterPanel::get_meters_width %d %d\n", BC_Meter::get_title_w(), BC_Meter::get_meter_w());
197         return visible ?
198                 (BC_Meter::get_title_w() +
199                         theme->widget_border +
200                         BC_Meter::get_meter_w() * meter_count +
201                         theme->widget_border * (meter_count - 1)) :
202                 0;
203 }
204
205
206 int MeterPanel::get_meter_w(int number)
207 {
208         int border = mwindow->theme->widget_border;
209         int meter_w;
210         if( w > 0 ) {
211                 meter_w = (w - BC_Meter::get_title_w() -
212                                 (meter_count - 1) * border) / meter_count;
213                 if( meter_w < 3 ) meter_w = 3;
214         }
215         else
216                 meter_w = BC_Meter::get_meter_w();
217         if( !number )
218                 meter_w += BC_Meter::get_title_w();
219         return meter_w;
220 }
221
222 int MeterPanel::get_meter_h()
223 {
224         int border = mwindow->theme->widget_border;
225         if(use_titles)
226         {
227                 return h - border - subwindow->get_text_height(SMALLFONT);
228         }
229         else
230         {
231                 return h;
232         }
233 }
234
235 void MeterPanel::update(double *levels)
236 {
237         if( !visible || subwindow->get_hidden()) return;
238
239
240         for(int i = 0; i < meter_count; i++)
241         {
242                 meters.values[i]->update(levels[i], levels[i] > 1.0);
243
244                 if(use_titles &&
245                         levels[i] > meter_peaks.get(i))
246                 {
247                         update_peak(i, levels[i]);
248                 }
249         }
250 }
251
252 void MeterPanel::init_meters(int dmix)
253 {
254         subwindow->lock_window("MeterPanel::init_meters");
255         for(int i = 0; i < meter_count; i++)
256         {
257                 meters.values[i]->reset(dmix);
258         }
259         subwindow->unlock_window();
260 }
261
262 void MeterPanel::update_peak(int number, float value)
263 {
264         if(use_titles && number < meter_count)
265         {
266                 meter_peaks.set(number, value);
267
268                 float db_value = DB::todb(value);
269                 char string[BCTEXTLEN] = { 0 };
270                 if(db_value <= mwindow->edl->session->min_meter_db)
271                 {
272                         sprintf(string, "oo");
273                 }
274                 else
275                 if(db_value > 0)
276                 {
277                         sprintf(string, "+%.1f",
278                                 db_value);
279                 }
280                 else
281                 {
282                         sprintf(string, "%.1f",
283                                 db_value);
284                 }
285
286                 meter_titles.get(number)->update(string);
287                 meter_titles.get(number)->reposition_window(get_title_x(number, string),
288                         meter_titles.get(number)->get_y());
289         }
290 }
291
292 void MeterPanel::stop_meters()
293 {
294         for(int i = 0; i < meter_count; i++)
295         {
296                 meters.values[i]->reset();
297 // Reset peak without drawing
298                 meter_peaks.set(i, 0);
299         }
300 }
301
302
303 void MeterPanel::reset_meters()
304 {
305         for(int i = 0; i < meters.size(); i++)
306                 meters.values[i]->reset_over();
307
308         for(int i = 0; i < meter_titles.size(); i++)
309         {
310                 update_peak(i, 0);
311         }
312 }
313
314
315 void MeterPanel::change_format(int mode, int min, int max)
316 {
317         for(int i = 0; i < meters.total; i++)
318         {
319                 if(use_headroom)
320                         meters.values[i]->change_format(mode, min, 0);
321                 else
322                         meters.values[i]->change_format(mode, min, max);
323         }
324 }
325
326
327
328
329
330
331
332
333
334 MeterReset::MeterReset(MWindow *mwindow, MeterPanel *panel, int x, int y)
335  : BC_Button(x, y, mwindow->theme->over_button)
336 {
337         this->mwindow = mwindow;
338         this->panel = panel;
339 }
340
341 MeterReset::~MeterReset()
342 {
343 }
344
345 int MeterReset::handle_event()
346 {
347         for(int i = 0; i < panel->meters.total; i++)
348                 panel->meters.values[i]->reset_over();
349         return 1;
350 }
351
352
353
354
355
356 MeterMeter::MeterMeter(MWindow *mwindow,
357         MeterPanel *panel, int x, int y, int w, int h, int titles)
358  : BC_Meter(x, y, METER_VERT, h, mwindow->edl->session->min_meter_db,
359         panel->use_headroom ? 0 : mwindow->edl->session->max_meter_db,
360         mwindow->edl->session->meter_format, titles, w)
361 {
362         this->mwindow = mwindow;
363         this->panel = panel;
364         set_delays(TRACKING_RATE * 10, TRACKING_RATE);
365 }
366
367 MeterMeter::~MeterMeter()
368 {
369 }
370
371
372 int MeterMeter::button_press_event()
373 {
374         if(is_event_win() && BC_WindowBase::cursor_inside())
375         {
376                 panel->reset_meters();
377                 mwindow->reset_meters();
378                 return 1;
379         }
380
381         return 0;
382 }
383
384
385
386
387
388 MeterShow::MeterShow(MWindow *mwindow, MeterPanel *panel, int x, int y)
389  : BC_Toggle(x,
390                 y,
391                 mwindow->theme->get_image_set("meters"),
392                 panel->visible)
393 {
394         this->mwindow = mwindow;
395         this->panel = panel;
396         set_tooltip(_("Show meters"));
397 }
398
399
400 MeterShow::~MeterShow()
401 {
402 }
403
404
405 int MeterShow::handle_event()
406 {
407 //printf("MeterShow::MeterShow 1 %d\n",panel->visible );
408 // need to detect a change in visible, outside here
409 //      panel->visible = get_value();
410         panel->change_status_event(get_value());
411         return 1;
412 }