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