r870: Merge 2.1:
[cinelerra_cv.git] / cinelerra / mtimebar.C
blobb1b19261c368031056efd7d7bb7595d78f97df16
1 #include "bcsignals.h"
2 #include "clip.h"
3 #include "cwindow.h"
4 #include "edl.h"
5 #include "edlsession.h"
6 #include "localsession.h"
7 #include "maincursor.h"
8 #include "mainsession.h"
9 #include "mbuttons.h"
10 #include "mtimebar.h"
11 #include "mwindowgui.h"
12 #include "mwindow.h"
13 #include "preferences.h"
14 #include "theme.h"
15 #include "trackcanvas.h"
16 #include "tracks.h"
17 #include "transportque.h"
18 #include "zoombar.h"
22 MTimeBar::MTimeBar(MWindow *mwindow, 
23         MWindowGUI *gui,
24         int x, 
25         int y,
26         int w,
27         int h)
28  : TimeBar(mwindow, gui, x, y, w, h)
30         this->gui = gui;
34 int64_t MTimeBar::position_to_pixel(double position)
36         return (int64_t)(position * 
37                 mwindow->edl->session->sample_rate / 
38                 mwindow->edl->local_session->zoom_sample - 
39                 mwindow->edl->local_session->view_start);
43 void MTimeBar::stop_playback()
45         gui->unlock_window();
46         gui->mbuttons->transport->handle_transport(STOP, 1, 0, 0);
47         gui->lock_window();
50 #define TEXT_MARGIN 4
51 #define TICK_SPACING 5
52 #define LINE_MARGIN 3
53 #define TICK_MARGIN 16
54 void MTimeBar::draw_time()
57         char string[BCTEXTLEN];
58         int sample_rate = mwindow->edl->session->sample_rate;
59         double frame_rate = mwindow->edl->session->frame_rate;
60         int64_t windowspan = 0;
61 // Seconds between text markings
62         double text_interval = 3600.0;
63 // Seconds between tick marks
64         double tick_interval = 3600.0;
65         int64_t timescale2 = 0;
66         float timescale3 = 0;
67         int pixel = 0;
70 // Calculate tick mark spacing, number spacing, and starting point based
71 // on zoom, time format, project settings.
73 // If the time format is for audio, mark round numbers of samples based on
74 // samplerate.
75 // Fow low zoom, mark tens of samples.
77 // If the time format is for video, mark round number of frames based on
78 // framerate.
79 // For low zoom, mark individual frames.
81         windowspan = mwindow->edl->local_session->zoom_sample * get_w();
84         draw_range();
90 // Number of seconds per pixel
91         double time_per_pixel = (double)mwindow->edl->local_session->zoom_sample / 
92                 sample_rate;
93 // Seconds in each frame
94         double frame_seconds = (double)1.0 / frame_rate;
95 // Starting time of view in seconds.
96         double view_start = mwindow->edl->local_session->view_start * time_per_pixel;
97 // Ending time of view in seconds
98         double view_end = (double)(mwindow->edl->local_session->view_start +
99                 get_w()) * time_per_pixel;
100 // Get minimum distance between text marks
101         int min_pixels1 = get_text_width(MEDIUMFONT, 
102                 Units::totext(string,
103                         view_start,
104                         mwindow->edl->session->time_format, 
105                         sample_rate,
106                         mwindow->edl->session->frame_rate,
107                         mwindow->edl->session->frames_per_foot)) + TEXT_MARGIN;
108         int min_pixels2 = get_text_width(MEDIUMFONT, 
109                 Units::totext(string,
110                         view_end,
111                         mwindow->edl->session->time_format, 
112                         sample_rate,
113                         mwindow->edl->session->frame_rate,
114                         mwindow->edl->session->frames_per_foot)) + TEXT_MARGIN;
115         int min_pixels = (int)MAX(min_pixels1, min_pixels2);
118 // Minimum seconds between text marks
119         double min_time = (double)min_pixels * 
120                 mwindow->edl->local_session->zoom_sample /
121                 sample_rate;
124 // Get first text mark on or before window start
125         int64_t starting_mark = 0;
127         int progression = 1;
129 // Default text spacing
130         text_interval = 0.5;
131         double prev_text_interval = 1.0;
133         while(text_interval >= min_time)
134         {
135                 prev_text_interval = text_interval;
136                 if(progression == 0)
137                 {
138                         text_interval /= 2;
139                         progression++;
140                 }
141                 else
142                 if(progression == 1)
143                 {
144                         text_interval /= 2;
145                         progression++;
146                 }
147                 else
148                 if(progression == 2)
149                 {
150                         text_interval /= 2.5;
151                         progression = 0;
152                 }
153         }
155         text_interval = prev_text_interval;
157         if(1 >= min_time)
158                 ;
159         else
160         if(2 >= min_time)
161                 text_interval = 2;
162         else
163         if(5 >= min_time)
164                 text_interval = 5;
165         else
166         if(10 >= min_time)
167                 text_interval = 10;
168         else
169         if(15 >= min_time)
170                 text_interval = 15;
171         else
172         if(20 >= min_time)
173                 text_interval = 20;
174         else
175         if(30 >= min_time)
176                 text_interval = 30;
177         else
178         if(60 >= min_time)
179                 text_interval = 60;
180         else
181         if(120 >= min_time)
182                 text_interval = 120;
183         else
184         if(300 >= min_time)
185                 text_interval = 300;
186         else
187         if(600 >= min_time)
188                 text_interval = 600;
189         else
190         if(1200 >= min_time)
191                 text_interval = 1200;
192         else
193         if(1800 >= min_time)
194                 text_interval = 1800;
195         else
196         if(3600 >= min_time)
197                 text_interval = 3600;
199 // Set text interval
200         switch(mwindow->edl->session->time_format)
201         {
202                 case TIME_FEET_FRAMES:
203                 {
204                         double foot_seconds = frame_seconds * mwindow->edl->session->frames_per_foot;
205                         if(frame_seconds >= min_time)
206                                 text_interval = frame_seconds;
207                         else
208                         if(foot_seconds / 8.0 > min_time)
209                                 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 8.0;
210                         else
211                         if(foot_seconds / 4.0 > min_time)
212                                 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 4.0;
213                         else
214                         if(foot_seconds / 2.0 > min_time)
215                                 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 2.0;
216                         else
217                         if(foot_seconds > min_time)
218                                 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot;
219                         else
220                         if(foot_seconds * 2 >= min_time)
221                                 text_interval = foot_seconds * 2;
222                         else
223                         if(foot_seconds * 5 >= min_time)
224                                 text_interval = foot_seconds * 5;
225                         else
226                         {
228                                 for(int factor = 10, progression = 0; factor <= 100000; )
229                                 {
230                                         if(foot_seconds * factor >= min_time)
231                                         {
232                                                 text_interval = foot_seconds * factor;
233                                                 break;
234                                         }
236                                         if(progression == 0)
237                                         {
238                                                 factor = (int)(factor * 2.5);
239                                                 progression++;
240                                         }
241                                         else
242                                         if(progression == 1)
243                                         {
244                                                 factor = (int)(factor * 2);
245                                                 progression++;
246                                         }
247                                         else
248                                         if(progression == 2)
249                                         {
250                                                 factor = (int)(factor * 2);
251                                                 progression = 0;
252                                         }
253                                 }
255                         }
256                         break;
257                 }
259                 case TIME_FRAMES:
260                 case TIME_HMSF:
261 // One frame per text mark
262                         if(frame_seconds >= min_time)
263                                 text_interval = frame_seconds;
264                         else
265                         if(frame_seconds * 2 >= min_time)
266                                 text_interval = frame_seconds * 2;
267                         else
268                         if(frame_seconds * 5 >= min_time)
269                                 text_interval = frame_seconds * 5;
270                         else
271                         {
273                                 for(int factor = 10, progression = 0; factor <= 100000; )
274                                 {
275                                         if(frame_seconds * factor >= min_time)
276                                         {
277                                                 text_interval = frame_seconds * factor;
278                                                 break;
279                                         }
281                                         if(progression == 0)
282                                         {
283                                                 factor = (int)(factor * 2.5);
284                                                 progression++;
285                                         }
286                                         else
287                                         if(progression == 1)
288                                         {
289                                                 factor = (int)(factor * 2);
290                                                 progression++;
291                                         }
292                                         else
293                                         if(progression == 2)
294                                         {
295                                                 factor = (int)(factor * 2);
296                                                 progression = 0;
297                                         }
298                                 }
300                         }
301                         break;
303                 default:
304                         break;
305         }
307 // Sanity
308         while(text_interval < min_time)
309         {
310                 text_interval *= 2;
311         }
313 // Set tick interval
314         tick_interval = text_interval;
316         switch(mwindow->edl->session->time_format)
317         {
318                 case TIME_HMSF:
319                 case TIME_FEET_FRAMES:
320                 case TIME_FRAMES:
321                         if(frame_seconds / time_per_pixel > TICK_SPACING)
322                                 tick_interval = frame_seconds;
323                         break;
324         }
326 // Get first text mark on or before window start
327         starting_mark = (int64_t)((double)mwindow->edl->local_session->view_start * 
328                 time_per_pixel / text_interval);
330         double start_position = (double)starting_mark * text_interval;
331         int64_t iteration = 0;
334 //printf("text_interval=%f\n", text_interval);
335         while(start_position + text_interval * iteration < view_end)
336         {
337                 double position1 = start_position + text_interval * iteration;
338                 int pixel = (int64_t)(position1 / time_per_pixel) - 
339                         mwindow->edl->local_session->view_start;
340                 int pixel1 = pixel;
342                 Units::totext(string, 
343                         position1, 
344                         mwindow->edl->session->time_format, 
345                         sample_rate, 
346                         mwindow->edl->session->frame_rate,
347                         mwindow->edl->session->frames_per_foot);
348                 set_color(get_resources()->default_text_color);
349                 set_font(MEDIUMFONT);
351                 draw_text(pixel + TEXT_MARGIN, get_text_ascent(MEDIUMFONT), string);
352                 draw_line(pixel, LINE_MARGIN, pixel, get_h() - 2);
354                 double position2 = start_position + text_interval * (iteration + 1);
355                 int pixel2 = (int64_t)(position2 / time_per_pixel) - 
356                         mwindow->edl->local_session->view_start;
358                 for(double tick_position = position1; 
359                         tick_position < position2; 
360                         tick_position += tick_interval)
361                 {
362                         pixel = (int64_t)(tick_position / time_per_pixel) - 
363                                 mwindow->edl->local_session->view_start;
364                         if(labs(pixel - pixel1) > 1 &&
365                                 labs(pixel - pixel2) > 1)
366                                 draw_line(pixel, TICK_MARGIN, pixel, get_h() - 2);
367                 }
368                 iteration++;
369         }
374 void MTimeBar::draw_range()
376         int x1 = 0, x2 = 0;
377         if(mwindow->edl->tracks->total_playable_vtracks() &&
378                 mwindow->preferences->use_brender)
379         {
380                 double time_per_pixel = (double)mwindow->edl->local_session->zoom_sample /
381                         mwindow->edl->session->sample_rate;
382                 x1 = (int)(mwindow->edl->session->brender_start / time_per_pixel) - 
383                         mwindow->edl->local_session->view_start;
384                 x2 = (int)(mwindow->session->brender_end / time_per_pixel) - 
385                         mwindow->edl->local_session->view_start;
386         }
388         if(x2 > x1 && 
389                 x1 < get_w() && 
390                 x2 > 0)
391         {
392                 draw_top_background(get_parent(), 0, 0, x1, get_h());
394                 draw_3segmenth(x1, 0, x2 - x1, mwindow->theme->get_image("timebar_brender"));
396                 draw_top_background(get_parent(), x2, 0, get_w() - x2, get_h());
397         }
398         else
399                 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
400 //printf("MTimeBar::draw_range %f %f\n", mwindow->session->brender_end, time_per_pixel);
403 void MTimeBar::select_label(double position)
405         EDL *edl = mwindow->edl;
407         mwindow->gui->unlock_window();
408         mwindow->gui->mbuttons->transport->handle_transport(STOP, 1, 0, 0);
409         mwindow->gui->lock_window();
411         position = mwindow->edl->align_to_frame(position, 1);
413         if(shift_down())
414         {
415                 if(position > edl->local_session->get_selectionend(1) / 2 + 
416                         edl->local_session->get_selectionstart(1) / 2)
417                 {
418                 
419                         edl->local_session->set_selectionend(position);
420                 }
421                 else
422                 {
423                         edl->local_session->set_selectionstart(position);
424                 }
425         }
426         else
427         {
428                 edl->local_session->set_selectionstart(position);
429                 edl->local_session->set_selectionend(position);
430         }
432 // Que the CWindow
433         mwindow->cwindow->update(1, 0, 0);
434         mwindow->gui->cursor->hide(0);
435         mwindow->gui->cursor->draw(1);
436         mwindow->gui->canvas->activate();
437         mwindow->gui->zoombar->update();
438         update_highlights();
439         mwindow->gui->canvas->flash();
443 int MTimeBar::resize_event()
445         reposition_window(mwindow->theme->mtimebar_x,
446                 mwindow->theme->mtimebar_y,
447                 mwindow->theme->mtimebar_w,
448                 mwindow->theme->mtimebar_h);
449         update();
450         return 1;
453 int MTimeBar::test_preview(int buttonpress)
455         int result = 0;
456         return result;