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