Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.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         for(int i = 0; i < meter_count; i++)
255         {
256                 meters.values[i]->reset(dmix);
257         }
258 }
259
260 void MeterPanel::update_peak(int number, float value)
261 {
262         if(use_titles && number < meter_count)
263         {
264                 meter_peaks.set(number, value);
265                 
266                 float db_value = DB::todb(value);
267                 char string[BCTEXTLEN] = { 0 };
268                 if(db_value <= mwindow->edl->session->min_meter_db)
269                 {
270                         sprintf(string, "oo");
271                 }
272                 else
273                 if(db_value > 0)
274                 {
275                         sprintf(string, "+%.1f", 
276                                 db_value);
277                 }
278                 else
279                 {
280                         sprintf(string, "%.1f", 
281                                 db_value);
282                 }
283
284                 meter_titles.get(number)->update(string);
285                 meter_titles.get(number)->reposition_window(get_title_x(number, string), 
286                         meter_titles.get(number)->get_y());
287         }
288 }
289
290 void MeterPanel::stop_meters()
291 {
292         for(int i = 0; i < meter_count; i++)
293         {
294                 meters.values[i]->reset();
295 // Reset peak without drawing
296                 meter_peaks.set(i, 0);
297         }
298 }
299
300
301 void MeterPanel::reset_meters()
302 {
303         for(int i = 0; i < meters.size(); i++)
304                 meters.values[i]->reset_over();
305
306         for(int i = 0; i < meter_titles.size(); i++)
307         {
308                 update_peak(i, 0);
309         }
310 }
311
312
313 void MeterPanel::change_format(int mode, int min, int max)
314 {
315         for(int i = 0; i < meters.total; i++)
316         {
317                 if(use_headroom)
318                         meters.values[i]->change_format(mode, min, 0);
319                 else
320                         meters.values[i]->change_format(mode, min, max);
321         }
322 }
323
324
325
326
327
328
329
330
331
332 MeterReset::MeterReset(MWindow *mwindow, MeterPanel *panel, int x, int y)
333  : BC_Button(x, y, mwindow->theme->over_button)
334 {
335         this->mwindow = mwindow;
336         this->panel = panel;
337 }
338
339 MeterReset::~MeterReset()
340 {
341 }
342         
343 int MeterReset::handle_event()
344 {
345         for(int i = 0; i < panel->meters.total; i++)
346                 panel->meters.values[i]->reset_over();
347         return 1;
348 }
349
350
351
352
353
354 MeterMeter::MeterMeter(MWindow *mwindow, 
355         MeterPanel *panel, int x, int y, int w, int h, int titles)
356  : BC_Meter(x, y, METER_VERT, h, mwindow->edl->session->min_meter_db, 
357         panel->use_headroom ? 0 : mwindow->edl->session->max_meter_db, 
358         mwindow->edl->session->meter_format, titles, w)
359 {
360         this->mwindow = mwindow;
361         this->panel = panel;
362         set_delays(TRACKING_RATE * 10, TRACKING_RATE);
363 }
364
365 MeterMeter::~MeterMeter()
366 {
367 }
368
369
370 int MeterMeter::button_press_event()
371 {
372         if(is_event_win() && BC_WindowBase::cursor_inside())
373         {
374                 panel->reset_meters();
375                 mwindow->reset_meters();
376                 return 1;
377         }
378
379         return 0;
380 }
381
382
383
384
385
386 MeterShow::MeterShow(MWindow *mwindow, MeterPanel *panel, int x, int y)
387  : BC_Toggle(x, 
388                 y, 
389                 mwindow->theme->get_image_set("meters"), 
390                 panel->visible)
391 {
392         this->mwindow = mwindow;
393         this->panel = panel;
394         set_tooltip(_("Show meters"));
395 }
396
397
398 MeterShow::~MeterShow()
399 {
400 }
401
402
403 int MeterShow::handle_event()
404 {
405 //printf("MeterShow::MeterShow 1 %d\n",panel->visible );
406 // need to detect a change in visible, outside here
407 //      panel->visible = get_value();
408         panel->change_status_event(get_value());
409         return 1;
410 }