cdc1e1b1d4b8b2d79a425f5bc8c4494cc22cf4a0
[goodguy/history.git] / cinelerra-5.1 / cinelerra / resourcepixmap.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 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
23
24 #include "arender.h"
25 #include "aedit.h"
26 #include "asset.h"
27 #include "asset.inc"
28 #include "automation.h"
29 #include "autos.h"
30 #include "bcsignals.h"
31 #include "cache.h"
32 #include "clip.h"
33 #include "bccmodels.h"
34 #include "datatype.h"
35 #include "edit.h"
36 #include "edits.h"
37 #include "edl.h"
38 #include "edlsession.h"
39 #include "file.h"
40 #include "filesystem.h"
41 #include "floatauto.h"
42 #include "floatautos.h"
43 #include "framecache.h"
44 #include "indexfile.h"
45 #include "language.h"
46 #include "localsession.h"
47 #include "mwindow.h"
48 #include "mwindowgui.h"
49 #include "renderengine.h"
50 #include "resourcethread.h"
51 #include "resourcepixmap.h"
52 #include "samples.h"
53 #include "theme.h"
54 #include "timelinepane.h"
55 #include "track.h"
56 #include "trackcanvas.h"
57 #include "transportque.h"
58 #include "vedit.h"
59 #include "vframe.h"
60 #include "wavecache.h"
61
62
63 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
64         MWindowGUI *gui,
65         Edit *edit,
66         int pane_number,
67         int w,
68         int h)
69  : BC_Pixmap(gui, w, h)
70 {
71         reset();
72
73         this->mwindow = mwindow;
74         this->gui = gui;
75         this->pane_number = pane_number;
76         startsource = edit->startsource;
77         data_type = edit->track->data_type;
78         if( edit->asset ) {
79                 source_framerate = edit->asset->frame_rate;
80                 source_samplerate = edit->asset->sample_rate;
81         }
82         else
83         if( edit->nested_edl ) {
84                 source_framerate = edit->nested_edl->session->frame_rate;
85                 source_samplerate = edit->nested_edl->session->sample_rate;
86         }
87
88         project_framerate = edit->edl->session->frame_rate;
89         project_samplerate = edit->edl->session->sample_rate;
90         edit_id = edit->id;  pixmap_w = w;  pixmap_h = h;
91 }
92
93 ResourcePixmap::~ResourcePixmap()
94 {
95 }
96
97
98 void ResourcePixmap::reset()
99 {
100         edit_x = 0;
101         pixmap_x = 0;
102         pixmap_w = 0;
103         pixmap_h = 0;
104         zoom_sample = 0;
105         zoom_track = 0;
106         zoom_y = 0;
107         visible = 1;
108 }
109
110 void ResourcePixmap::resize(int w, int h)
111 {
112         int new_w = (w > get_w()) ? w : get_w();
113         int new_h = (h > get_h()) ? h : get_h();
114
115         BC_Pixmap::resize(new_w, new_h);
116 }
117
118
119 void ResourcePixmap::draw_data(TrackCanvas *canvas,
120         Edit *edit, int64_t edit_x, int64_t edit_w,
121         int64_t pixmap_x, int64_t pixmap_w, int64_t pixmap_h,
122         int mode, int indexes_only)
123 {
124 // Get new areas to fill in relative to pixmap
125 // Area to redraw relative to pixmap
126         int refresh_x = 0;
127         int refresh_w = 0;
128
129 // Ignore if called by resourcethread.
130 //      if( mode == IGNORE_THREAD ) return;
131
132         int y = 0;
133         if( edit->track->show_titles() )
134                 y += mwindow->theme->get_image("title_bg_data")->get_h();
135
136
137 // If want indexes only & index can't be drawn, don't do anything.
138         int need_redraw = 0;
139         int64_t index_zoom = 0;
140         Indexable *indexable = 0;
141         if( edit->asset ) indexable = edit->asset;
142         if( edit->nested_edl ) indexable = edit->nested_edl;
143         if( indexable && indexes_only ) {
144                 IndexFile indexfile(mwindow, indexable);
145                 if( !indexfile.open_index() ) {
146                         index_zoom = indexable->index_state->index_zoom;
147                         indexfile.close_index();
148                 }
149
150                 if( index_zoom ) {
151                         if( data_type == TRACK_AUDIO ) {
152                                 double asset_over_session = (double)indexable->get_sample_rate() /
153                                         mwindow->edl->session->sample_rate;
154                                 if( index_zoom <= mwindow->edl->local_session->zoom_sample *
155                                         asset_over_session )
156                                         need_redraw = 1;
157                         }
158                 }
159
160                 if( !need_redraw )
161                         return;
162         }
163
164
165 // Redraw everything
166 /* Incremental drawing is not possible with resource thread */
167         if( 1 )
168 //              edit->startsource != this->startsource ||
169 //              mwindow->edl->session->sample_rate != project_samplerate ||
170 //              !EQUIV(mwindow->edl->session->frame_rate, project_framerate) ||
171 //              mwindow->edl->local_session->zoom_sample != zoom_sample ||
172 //              mwindow->edl->local_session->zoom_track != zoom_track ||
173 //              this->pixmap_h != pixmap_h ||
174 //              (data_type == TRACK_AUDIO &&
175 //                      mwindow->edl->local_session->zoom_y != zoom_y) ||
176 //              (mode == 2) ||
177 //              need_redraw)
178         {
179 // Redraw the whole thing.
180                 refresh_x = 0;
181                 refresh_w = pixmap_w;
182         }
183         else {
184 // Start translated right
185                 if( pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w ) {
186                         refresh_w = this->edit_x - edit_x;
187                         refresh_x = this->pixmap_w - refresh_w;
188
189 // Moved completely off the pixmap
190                         if( refresh_w > this->pixmap_w ) {
191                                 refresh_w = this->pixmap_w;
192                                 refresh_x = 0;
193                         }
194                         else {
195                                 copy_area(refresh_w,
196                                         y,
197                                         refresh_x,
198                                         mwindow->edl->local_session->zoom_track,
199                                         0,
200                                         y);
201                         }
202                 }
203                 else
204 // Start translated left
205                 if( pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w ) {
206                         refresh_x = 0;
207                         refresh_w = edit_x - this->edit_x;
208
209 // Moved completely off the pixmap
210                         if( refresh_w > this->pixmap_w ) {
211                                 refresh_w = this->pixmap_w;
212                         }
213                         else {
214                                 copy_area(0,
215                                         y,
216                                         this->pixmap_w - refresh_w,
217                                         mwindow->edl->local_session->zoom_track,
218                                         refresh_w,
219                                         y);
220                         }
221                 }
222                 else
223 // Start translated right and pixmap came off of right side
224                 if( pixmap_w < this->pixmap_w && edit_x < this->edit_x &&
225                         this->edit_x + edit_w > this->pixmap_x + this->pixmap_w ) {
226                         refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
227                         refresh_x = pixmap_w - refresh_w;
228
229                         if( refresh_w >= pixmap_w ) {
230                                 refresh_x = 0;
231                                 refresh_w = pixmap_w;
232                         }
233                         else {
234                                 copy_area(this->edit_x - edit_x,
235                                         y,
236                                         pixmap_w - refresh_w,
237                                         mwindow->edl->local_session->zoom_track,
238                                         0,
239                                         y);
240                         }
241                 }
242                 else
243 // Start translated right and reduced in size on the right.
244                 if( pixmap_w < this->pixmap_w && edit_x < this->edit_x ) {
245                         refresh_x = 0;
246                         refresh_w = 0;
247
248                         copy_area(this->pixmap_w - pixmap_w,
249                                 y,
250                                 pixmap_w,
251                                 mwindow->edl->local_session->zoom_track,
252                                 0,
253                                 y);
254                 }
255                 else
256 // Start translated left and pixmap came off left side
257                 if( edit_x >= 0 && this->edit_x < 0 ) {
258                         refresh_x = 0;
259                         refresh_w = -this->edit_x;
260
261                         if( refresh_w > pixmap_w ) {
262                                 refresh_w = pixmap_w;
263                         }
264                         else {
265                                 copy_area(0,
266                                                 y,
267                                                 this->pixmap_w,
268                                                 mwindow->edl->local_session->zoom_track,
269                                                 refresh_w,
270                                                 y);
271                         }
272                 }
273                 else
274 // Start translated left and reduced in size on the right
275                 if( pixmap_w < this->pixmap_w && edit_x > this->edit_x ) {
276                         refresh_x = 0;
277                         refresh_w = 0;
278                 }
279                 else
280 // Start translated right and left went into left side.
281                 if( pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0 ) {
282                         refresh_w = pixmap_w - (edit_x + this->pixmap_w);
283                         refresh_x = pixmap_w - refresh_w;
284
285 // Moved completely off new pixmap
286                         if( refresh_w > pixmap_w ) {
287                                 refresh_w = pixmap_w;
288                                 refresh_x = 0;
289                         }
290                         else {
291                                 copy_area(-edit_x,
292                                         y,
293                                         refresh_x,
294                                         mwindow->edl->local_session->zoom_track,
295                                         0,
296                                         y);
297                         }
298                 }
299                 else
300 // Start translated right and increased in size on the right
301                 if( pixmap_w > this->pixmap_w && edit_x <= this->edit_x ) {
302                         refresh_w = pixmap_w - this->pixmap_w;
303                         refresh_x = pixmap_w - refresh_w;
304                 }
305                 else
306 // Start translated left and increased in size on the right
307                 if( pixmap_w > this->pixmap_w && edit_x > this->edit_x ) {
308                         refresh_x = 0;
309                         refresh_w = edit_x - this->edit_x;
310
311 // Moved completely off new pixmap
312                         if( refresh_w > this->pixmap_w ) {
313                                 refresh_w = pixmap_w;
314                                 refresh_x = 0;
315                         }
316 // Shift and insert
317                         else {
318                                 copy_area(0,
319                                         y,
320                                         this->pixmap_w,
321                                         mwindow->edl->local_session->zoom_track,
322                                         refresh_w,
323                                         y);
324                         }
325                 }
326         }
327
328 // Update pixmap settings
329         this->edit_id = edit->id;
330         this->startsource = edit->startsource;
331
332         if( edit->asset )
333                 this->source_framerate = edit->asset->frame_rate;
334         else
335         if( edit->nested_edl )
336                 this->source_framerate = edit->nested_edl->session->frame_rate;
337
338         if( edit->asset )
339                 this->source_samplerate = edit->asset->sample_rate;
340         else
341         if( edit->nested_edl )
342                 this->source_samplerate = edit->nested_edl->session->sample_rate;
343
344         this->project_framerate = edit->edl->session->frame_rate;
345         this->project_samplerate = edit->edl->session->sample_rate;
346         this->edit_x = edit_x;
347         this->pixmap_x = pixmap_x;
348         this->pixmap_w = pixmap_w;
349         this->pixmap_h = pixmap_h;
350         this->zoom_sample = mwindow->edl->local_session->zoom_sample;
351         this->zoom_track = mwindow->edl->local_session->zoom_track;
352         this->zoom_y = mwindow->edl->local_session->zoom_y;
353
354
355
356 // Draw background image
357         if( refresh_w > 0 )
358                 mwindow->theme->draw_resource_bg(canvas,
359                         this,
360                         edit_x,
361                         edit_w,
362                         pixmap_x,
363                         refresh_x,
364                         y,
365                         refresh_x + refresh_w,
366                         mwindow->edl->local_session->zoom_track + y);
367 //printf("ResourcePixmap::draw_data 70\n");
368
369
370 // Draw media which already exists
371         Track *track = edit->track;
372         if( track->draw ) {
373                 switch( track->data_type )
374                 {
375                         case TRACK_AUDIO:
376                                 draw_audio_resource(canvas,
377                                         edit,
378                                         refresh_x,
379                                         refresh_w);
380                                 break;
381
382                         case TRACK_VIDEO:
383                                 draw_video_resource(canvas,
384                                         edit,
385                                         edit_x,
386                                         edit_w,
387                                         pixmap_x,
388                                         pixmap_w,
389                                         refresh_x,
390                                         refresh_w,
391                                         mode);
392                                 break;
393
394                         case TRACK_SUBTITLE:
395                                 draw_subttl_resource(canvas,
396                                         edit,
397                                         refresh_x,
398                                         refresh_w);
399                                 break;
400                 }
401         }
402 SET_TRACE
403 }
404
405 void ResourcePixmap::draw_title(TrackCanvas *canvas,
406         Edit *edit, int64_t edit_x, int64_t edit_w,
407         int64_t pixmap_x, int64_t pixmap_w)
408 {
409 // coords relative to pixmap
410         int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
411         int64_t x = total_x, w = total_w;
412         int left_margin = 10;
413
414         if( x < 0 ) { w -= -x; x = 0; }
415         if( w > pixmap_w ) w -= w - pixmap_w;
416
417         canvas->draw_3segmenth(x, 0, w, total_x, total_w,
418                 mwindow->theme->get_image("title_bg_data"), this);
419
420 //      if( total_x > -BC_INFINITY ) {
421                 char title[BCTEXTLEN];
422                 edit->get_title(title);
423                 canvas->set_color(mwindow->theme->title_color);
424                 canvas->set_font(mwindow->theme->title_font);
425
426 // Justify the text on the left boundary of the edit if it is visible.
427 // Otherwise justify it on the left side of the screen.
428                 int text_x = total_x + left_margin;
429                 text_x = MAX(left_margin, text_x);
430 //printf("ResourcePixmap::draw_title 1 %d\n", text_x);
431                 canvas->draw_text(text_x,
432                         canvas->get_text_ascent(mwindow->theme->title_font) + 2,
433                         title, strlen(title), this);
434 //      }
435 }
436
437
438 // Need to draw one more x
439 void ResourcePixmap::draw_audio_resource(TrackCanvas *canvas, Edit *edit, int x, int w)
440 {
441         if( w <= 0 ) return;
442         if( !edit->asset && !edit->nested_edl ) return;
443         Indexable *indexable = 0;
444         if( edit->asset ) indexable = edit->asset;
445         if( edit->nested_edl ) indexable = edit->nested_edl;
446 // printf("ResourcePixmap::draw_audio_resource %d x=%d w=%d\n", __LINE__, x, w);
447 SET_TRACE
448
449         IndexState *index_state = indexable->index_state;
450         double asset_over_session = (double)indexable->get_sample_rate() /
451                 mwindow->edl->session->sample_rate;
452
453 // Develop strategy for drawing
454 // printf("ResourcePixmap::draw_audio_resource %d %p %d\n",
455 // __LINE__,
456 // index_state,
457 // index_state->index_status);
458         switch( index_state->index_status )
459         {
460                 case INDEX_NOTTESTED:
461                         return;
462                         break;
463 // Disabled.  All files have an index.
464 //              case INDEX_TOOSMALL:
465 //                      draw_audio_source(canvas, edit, x, w);
466 //                      break;
467                 case INDEX_BUILDING:
468                 case INDEX_READY:
469                 {
470                         IndexFile indexfile(mwindow, indexable);
471                         if( !indexfile.open_index() ) {
472                                 if( index_state->index_zoom >
473                                                 mwindow->edl->local_session->zoom_sample *
474                                                 asset_over_session ) {
475 //printf("ResourcePixmap::draw_audio_resource %d\n", __LINE__);
476
477                                         draw_audio_source(canvas, edit, x, w);
478                                 }
479                                 else {
480 //printf("ResourcePixmap::draw_audio_resource %d\n", __LINE__);
481                                         indexfile.draw_index(canvas,
482                                                 this,
483                                                 edit,
484                                                 x,
485                                                 w);
486 SET_TRACE
487                                 }
488
489                                 indexfile.close_index();
490 SET_TRACE
491                         }
492                         break;
493                 }
494         }
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514 void ResourcePixmap::draw_audio_source(TrackCanvas *canvas, Edit *edit, int x, int w)
515 {
516         w++;
517         Indexable *indexable = edit->get_source();
518         int center_pixel = mwindow->edl->local_session->zoom_track / 2;
519         if( edit->track->show_titles() )
520                 center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
521         int64_t scale_y = mwindow->edl->local_session->zoom_y;
522         int y_max = center_pixel + scale_y / 2 - 1;
523
524         double project_zoom = mwindow->edl->local_session->zoom_sample;
525         FloatAutos *speed_autos = !edit->track->has_speed() ? 0 :
526                 (FloatAutos *)edit->track->automation->autos[AUTOMATION_SPEED];
527         int64_t edit_position = (x + pixmap_x - edit_x) * project_zoom;
528         int64_t start_position = edit->startsource;
529         start_position += !speed_autos ? edit_position :
530                 speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
531         int64_t end_position = edit->startsource;
532         edit_position = (x + w + pixmap_x - edit_x) * project_zoom;
533         end_position += !speed_autos ? edit_position :
534                 speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
535
536         double session_sample_rate = mwindow->edl->session->sample_rate;
537         double asset_over_session = (double)indexable->get_sample_rate() / session_sample_rate;
538         start_position *= asset_over_session;
539         end_position *= asset_over_session;
540         int sample_size = end_position - start_position;
541         if( sample_size < 0 ) sample_size = 0;
542         int source_samples = sample_size + 1;
543
544 // Single sample zoom
545         if( mwindow->edl->local_session->zoom_sample == 1 ) {
546                 Samples *buffer = 0;
547                 int result = 0;
548                 canvas->set_color(mwindow->theme->audio_color);
549
550                 if( indexable->is_asset ) {
551                         mwindow->gui->unlock_window();
552                         File *source = mwindow->audio_cache->check_out(edit->asset, mwindow->edl);
553                         mwindow->gui->lock_window("draw_audio_source");
554
555                         if( !source ) {
556                                 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
557                                 return;
558                         }
559
560                         source->set_audio_position(start_position);
561                         source->set_channel(edit->channel);
562                         buffer = new Samples(source_samples);
563                         result = source->read_samples(buffer, source_samples);
564                         mwindow->audio_cache->check_in(edit->asset);
565                 }
566                 else {
567                         if( mwindow->gui->render_engine &&
568                                 mwindow->gui->render_engine_id != indexable->id ) {
569                                 delete mwindow->gui->render_engine;
570                                 mwindow->gui->render_engine = 0;
571                         }
572
573                         if( !mwindow->gui->render_engine ) {
574                                 TransportCommand command;
575                                 command.command = NORMAL_FWD;
576                                 command.get_edl()->copy_all(edit->nested_edl);
577                                 command.change_type = CHANGE_ALL;
578                                 command.realtime = 0;
579                                 mwindow->gui->render_engine = new RenderEngine(0,
580                                         mwindow->preferences, 0, 0);
581                                 mwindow->gui->render_engine_id = edit->nested_edl->id;
582                                 mwindow->gui->render_engine->set_acache(mwindow->audio_cache);
583                                 mwindow->gui->render_engine->arm_command(&command);
584                         }
585
586                         if( mwindow->gui->render_engine->arender ) {
587                                 Samples *buffers[MAX_CHANNELS];
588                                 memset(buffers, 0, sizeof(buffers));
589                                 int nch = indexable->get_audio_channels(), ch = edit->channel;
590                                 for( int i=0; i<nch; ++i )
591                                         buffers[i] = new Samples(source_samples);
592                                 mwindow->gui->render_engine->arender->process_buffer(
593                                         buffers, source_samples, start_position);
594                                 for( int i=0; i<nch; ++i )
595                                         if( i != ch ) delete buffers[i];
596                                 buffer = buffers[ch];
597                         }
598                 }
599
600                 if( !result ) {
601                         double *samples = buffer->get_data();
602                         int y1 = center_pixel - samples[0] * scale_y / 2;
603                         int y2 = CLIP(y1, 0, y_max);
604
605                         for( int x0=0; x0<w; ++x0 ) {
606                                 int x1 = x0 + x, x2 = x1 + 1;
607                                 edit_position = (x1 + pixmap_x - edit_x) * project_zoom;
608                                 int64_t speed_position = edit->startsource;
609                                 speed_position += !speed_autos ? edit_position :
610                                         speed_autos->automation_integral(
611                                                 edit->startproject, edit_position, PLAY_FORWARD);
612                                 int j = speed_position * asset_over_session - start_position;
613                                 CLAMP(j, 0, sample_size);
614                                 int y0 = y2;
615                                 y1 = center_pixel - samples[j] * scale_y / 2;
616                                 y2 = CLIP(y1, 0, y_max);
617 //printf("ResourcePixmap::draw_audio_source %d %d %d\n", __LINE__, y1, y2);
618                                 canvas->draw_line(x0, y0, x2, y2, this);
619                         }
620                 }
621
622                 delete buffer;
623         }
624         else {
625                 edit_position = (x + pixmap_x - edit_x) * project_zoom;
626                 int64_t speed_position = edit->startsource;
627                 speed_position += !speed_autos ? edit_position :
628                         speed_autos->automation_integral(
629                                 edit->startproject, edit_position, PLAY_FORWARD);
630                 int64_t next_position = asset_over_session * speed_position;
631 // Multiple sample zoom
632                 int first_pixel = 1, prev_y1 = -1, prev_y2 = y_max;
633                 canvas->set_color(mwindow->theme->audio_color);
634                 ++x;
635
636 // Draw each pixel from the cache
637 //printf("ResourcePixmap::draw_audio_source %d x=%d w=%d\n", __LINE__, x, w);
638                 for( int x2=x+w; x<x2; ++x ) {
639                         int64_t prev_position = next_position;
640                         edit_position = (x + pixmap_x - edit_x) * project_zoom;
641                         speed_position = edit->startsource;
642                         speed_position += !speed_autos ? edit_position :
643                                 speed_autos->automation_integral(
644                                         edit->startproject, edit_position, PLAY_FORWARD);
645                         next_position = speed_position * asset_over_session;
646 // Starting sample of pixel relative to asset rate.
647                         WaveCacheItem *item = mwindow->wave_cache->get_wave(indexable->id,
648                                         edit->channel, prev_position, next_position);
649                         if( item ) {
650 //printf("ResourcePixmap::draw_audio_source %d\n", __LINE__);
651                                 int y_lo = (int)(center_pixel - item->low * scale_y / 2);
652                                 int y1 = CLIP(y_lo, 0, y_max);
653                                 int y_hi = (int)(center_pixel - item->high * scale_y / 2);
654                                 int y2 = CLIP(y_hi, 0, y_max);
655                                 if( !first_pixel ) {
656                                         y_lo = MIN(y1,prev_y2);
657                                         y_hi = MAX(y2,prev_y1);
658                                 }
659                                 else {
660                                         first_pixel = 0;
661                                         y_lo = y1;  y_hi = y2;
662                                 }
663                                 prev_y1 = y1;  prev_y2 = y2;
664                                 canvas->draw_line(x, y_lo, x, y_hi, this);
665 //printf("ResourcePixmap::draw_audio_source %d %d %d %d\n", __LINE__, x, y1, y2);
666                                 mwindow->wave_cache->unlock();
667                         }
668                         else {
669 //printf("ResourcePixmap::draw_audio_source %d\n", __LINE__);
670                                 gui->resource_thread->add_wave(this,
671                                         canvas->pane->number, indexable, x,
672                                         edit->channel, prev_position, next_position);
673                                 first_pixel = 1;  prev_y1 = -1;  prev_y2 = y_max;
674                         }
675                 }
676         }
677
678         canvas->test_timer();
679 }
680
681 void ResourcePixmap::draw_wave(TrackCanvas *canvas,
682         int x, double high, double low)
683 {
684         int top_pixel = 0;
685         if( mwindow->edl->session->show_titles )
686                 top_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
687         int center_pixel = mwindow->edl->local_session->zoom_track / 2 + top_pixel;
688         int bottom_pixel = top_pixel + mwindow->edl->local_session->zoom_track;
689         int y1 = (int)(center_pixel -
690                 low * mwindow->edl->local_session->zoom_y / 2);
691         int y2 = (int)(center_pixel -
692                 high * mwindow->edl->local_session->zoom_y / 2);
693         CLAMP(y1, top_pixel, bottom_pixel);
694         CLAMP(y2, top_pixel, bottom_pixel);
695         canvas->set_color(mwindow->theme->audio_color);
696         canvas->draw_line(x, y1, x, y2, this);
697 }
698
699
700 void ResourcePixmap::draw_video_resource(TrackCanvas *canvas,
701         Edit *edit, int64_t edit_x, int64_t edit_w, int64_t pixmap_x, int64_t pixmap_w,
702         int refresh_x, int refresh_w, int mode)
703 {
704 //PRINT_TRACE
705 //BC_Signals::dump_stack();
706
707 // pixels spanned by a picon
708         int64_t picon_w = Units::round(edit->picon_w());
709         int64_t picon_h = edit->picon_h();
710 //      if( picon_w <= 0 || picon_w > edit_w ) return;
711 // Don't draw video if picon is empty, or edit only hairline
712         if( picon_w < 1 || edit_w < 2 ) return;
713 // or bigger than edit and fills at less than 1.5 percent timeline
714         if( picon_w > edit_w && edit_w < canvas->get_w()/64 ) return;
715
716 // Frames spanned by a picon
717         double frame_w = edit->frame_w();
718 // pixels spanned by a frame
719         if( frame_w < picon_w ) frame_w = picon_w;
720 // Current pixel relative to pixmap
721         int y = 0;
722         if( edit->track->show_titles() )
723                 y += mwindow->theme->get_image("title_bg_data")->get_h();
724
725 // Frame in project touched by current pixel
726         FloatAutos *speed_autos = !edit->track->has_speed() ? 0 :
727                 (FloatAutos *)edit->track->automation->autos[AUTOMATION_SPEED];
728         Indexable *indexable = edit->get_source();
729         double session_sample_rate = mwindow->edl->session->sample_rate;
730         double project_zoom = mwindow->edl->local_session->zoom_sample / session_sample_rate;
731         int skip_frames = Units::to_int64(((int64_t)refresh_x + pixmap_x - edit_x) / frame_w);
732         int x = Units::to_int64(skip_frames * frame_w) + edit_x - pixmap_x;
733
734 // Draw only cached frames
735         while( x < refresh_x + refresh_w ) {
736                 int64_t edit_position =
737                         edit->track->to_units((x + pixmap_x - edit_x) * project_zoom, 0);
738                 int64_t speed_position = edit->startsource;
739                 speed_position += !speed_autos ? edit_position :
740                          speed_autos->automation_integral(
741                                 edit->startproject, edit_position, PLAY_FORWARD);
742                 VFrame *picon_frame = indexable->id < 0 ? 0 :
743                         mwindow->frame_cache->get_frame_ptr(speed_position, edit->channel,
744                                 mwindow->edl->session->frame_rate, BC_RGB888,
745                                 picon_w, picon_h, indexable->id);
746                 if( picon_frame ) {
747                         draw_vframe(picon_frame, x, y, picon_w, picon_h, 0, 0);
748                         mwindow->frame_cache->unlock();
749                 }
750                 else if( mode != IGNORE_THREAD ) {
751 // Set picon thread to draw in background
752 // printf("ResourcePixmap::draw_video_resource %d %d %lld\n",
753 // __LINE__, mwindow->frame_cache->total(), source_frame);
754                         gui->resource_thread->add_picon(this, canvas->pane->number, x, y,
755                                 picon_w, picon_h, mwindow->edl->session->frame_rate,
756                                 speed_position, edit->channel, indexable);
757                 }
758                 x += frame_w;
759                 canvas->test_timer();
760         }
761 }
762
763 #include "strack.h"
764
765 void ResourcePixmap::draw_subttl_resource(TrackCanvas *canvas, Edit *edit, int x, int w)
766 {
767         SEdit *sedit = (SEdit *)edit;
768         char *text = sedit->get_text();
769         if( !*text || w < 10 ) return;
770         int center_pixel = canvas->resource_h() / 2;
771         if( edit->track->show_titles() )
772                 center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
773         int64_t scale_y = mwindow->edl->local_session->zoom_y;
774         int x0 = edit_x;
775         if( x0 < 0 ) x0 = -x0;
776         int x1 = (int)(pixmap_x - x0 + x);
777         int y_max = center_pixel + scale_y / 2 - 1;
778         int font = MEDIUMFONT, color = WHITE;
779         canvas->set_font(font);
780         canvas->set_color(color);
781         int ch = canvas->get_text_height(font);
782         int hh = canvas->get_text_height(font,text) + ch/2;
783         int y1 = y_max - hh - 10;
784         if( y1 < 0 ) y1 = 0;
785         canvas->draw_text(x1, y1, text, -1, this);
786 }
787
788 void ResourcePixmap::dump()
789 {
790         printf("ResourcePixmap %p\n", this);
791         printf(" edit %jx edit_x %jd pixmap_x %jd pixmap_w %jd visible %d\n",
792                 edit_id, edit_x, pixmap_x, pixmap_w, visible);
793 }
794