6 #include "colormodels.h"
11 #include "edlsession.h"
13 #include "filesystem.h"
14 #include "framecache.h"
15 #include "indexfile.h"
17 #include "localsession.h"
19 #include "resourcethread.h"
20 #include "resourcepixmap.h"
23 #include "trackcanvas.h"
26 #include "wavecache.h"
29 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
34 : BC_Pixmap(canvas, w, h)
38 this->mwindow = mwindow;
39 this->canvas = canvas;
40 startsource = edit->startsource;
41 data_type = edit->track->data_type;
42 source_framerate = edit->asset->frame_rate;
43 project_framerate = edit->edl->session->frame_rate;
44 source_samplerate = edit->asset->sample_rate;
45 project_samplerate = edit->edl->session->sample_rate;
49 ResourcePixmap::~ResourcePixmap()
54 void ResourcePixmap::reset()
66 void ResourcePixmap::resize(int w, int h)
68 int new_w = (w > get_w()) ? w : get_w();
69 int new_h = (h > get_h()) ? h : get_h();
71 BC_Pixmap::resize(new_w, new_h);
75 void ResourcePixmap::draw_data(Edit *edit,
84 // Get new areas to fill in relative to pixmap
85 // Area to redraw relative to pixmap
89 // Ignore if called by resourcethread.
93 if(mwindow->edl->session->show_titles) y += mwindow->theme->get_image("title_bg_data")->get_h();
94 Track *track = edit->edits->track;
97 // If index can't be drawn, don't do anything.
99 int64_t index_zoom = 0;
102 IndexFile indexfile(mwindow);
103 if(!indexfile.open_index(edit->asset))
105 index_zoom = edit->asset->index_zoom;
106 indexfile.close_index();
111 if(data_type == TRACK_AUDIO)
113 double asset_over_session = (double)edit->asset->sample_rate /
114 mwindow->edl->session->sample_rate;
116 if(index_zoom <= mwindow->edl->local_session->zoom_sample *
128 if(edit->startsource != this->startsource ||
129 /* Incremental drawing is not possible with resource thread */
130 (data_type == TRACK_AUDIO /* &&
131 edit->asset->sample_rate != source_samplerate*/ ) ||
132 (data_type == TRACK_VIDEO /* &&
133 !EQUIV(edit->asset->frame_rate, source_framerate) */ ) ||
134 mwindow->edl->session->sample_rate != project_samplerate ||
135 mwindow->edl->session->frame_rate != project_framerate ||
136 mwindow->edl->local_session->zoom_sample != zoom_sample ||
137 mwindow->edl->local_session->zoom_track != zoom_track ||
138 this->pixmap_h != pixmap_h ||
139 (data_type == TRACK_AUDIO &&
140 mwindow->edl->local_session->zoom_y != zoom_y) ||
144 // Shouldn't draw at all if zoomed in below index zoom.
146 refresh_w = pixmap_w;
150 // Start translated right
151 if(pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w)
153 refresh_w = this->edit_x - edit_x;
154 refresh_x = this->pixmap_w - refresh_w;
156 // Moved completely off the pixmap
157 if(refresh_w > this->pixmap_w)
159 refresh_w = this->pixmap_w;
167 mwindow->edl->local_session->zoom_track,
173 // Start translated left
174 if(pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w)
177 refresh_w = edit_x - this->edit_x;
179 // Moved completely off the pixmap
180 if(refresh_w > this->pixmap_w)
182 refresh_w = this->pixmap_w;
188 this->pixmap_w - refresh_w,
189 mwindow->edl->local_session->zoom_track,
195 // Start translated right and pixmap came off of right side
196 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x &&
197 this->edit_x + edit_w > this->pixmap_x + this->pixmap_w)
199 refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
200 refresh_x = pixmap_w - refresh_w;
202 if(refresh_w >= pixmap_w)
205 refresh_w = pixmap_w;
209 copy_area(this->edit_x - edit_x,
211 pixmap_w - refresh_w,
212 mwindow->edl->local_session->zoom_track,
218 // Start translated right and reduced in size on the right.
219 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x)
224 copy_area(this->pixmap_w - pixmap_w,
227 mwindow->edl->local_session->zoom_track,
232 // Start translated left and pixmap came off left side
233 if(edit_x >= 0 && this->edit_x < 0)
236 refresh_w = -this->edit_x;
238 if(refresh_w > pixmap_w)
240 refresh_w = pixmap_w;
247 mwindow->edl->local_session->zoom_track,
253 // Start translated left and reduced in size on the right
254 if(pixmap_w < this->pixmap_w && edit_x > this->edit_x)
260 // Start translated right and left went into left side.
261 if(pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0)
263 refresh_w = pixmap_w - (edit_x + this->pixmap_w);
264 refresh_x = pixmap_w - refresh_w;
266 // Moved completely off new pixmap
267 if(refresh_w > pixmap_w)
269 refresh_w = pixmap_w;
277 mwindow->edl->local_session->zoom_track,
283 // Start translated right and increased in size on the right
284 if(pixmap_w > this->pixmap_w && edit_x <= this->edit_x)
286 refresh_w = pixmap_w - this->pixmap_w;
287 refresh_x = pixmap_w - refresh_w;
290 // Start translated left and increased in size on the right
291 if(pixmap_w > this->pixmap_w && edit_x > this->edit_x)
294 refresh_w = edit_x - this->edit_x;
296 // Moved completely off new pixmap
297 if(refresh_w > this->pixmap_w)
299 refresh_w = pixmap_w;
308 mwindow->edl->local_session->zoom_track,
315 // Update pixmap settings
316 this->edit_id = edit->id;
317 this->startsource = edit->startsource;
318 this->source_framerate = edit->asset->frame_rate;
319 this->source_samplerate = edit->asset->sample_rate;
320 this->project_framerate = edit->edl->session->frame_rate;
321 this->project_samplerate = edit->edl->session->sample_rate;
322 this->edit_x = edit_x;
323 this->pixmap_x = pixmap_x;
324 this->pixmap_w = pixmap_w;
325 this->pixmap_h = pixmap_h;
326 this->zoom_sample = mwindow->edl->local_session->zoom_sample;
327 this->zoom_track = mwindow->edl->local_session->zoom_track;
328 this->zoom_y = mwindow->edl->local_session->zoom_y;
332 // Draw in new background
334 mwindow->theme->draw_resource_bg(canvas,
341 refresh_x + refresh_w,
342 mwindow->edl->local_session->zoom_track + y);
343 //printf("ResourcePixmap::draw_data 70\n");
349 switch(track->data_type)
352 draw_audio_resource(edit, refresh_x, refresh_w);
356 draw_video_resource(edit,
369 if(mwindow->edl->session->show_titles)
370 draw_title(edit, edit_x, edit_w, pixmap_x, pixmap_w);
373 void ResourcePixmap::draw_title(Edit *edit,
379 // coords relative to pixmap
380 int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
381 int64_t x = total_x, w = total_w;
382 int left_margin = 10;
389 if(w > pixmap_w) w -= w - pixmap_w;
391 canvas->draw_3segmenth(x,
396 mwindow->theme->get_image("title_bg_data"),
399 if(total_x > -BC_INFINITY)
401 char title[BCTEXTLEN], channel[BCTEXTLEN];
404 if(edit->user_title[0])
405 strcpy(title, edit->user_title);
408 fs.extract_name(title, edit->asset->path);
410 sprintf(channel, " #%d", edit->channel + 1);
411 strcat(title, channel);
414 canvas->set_color(mwindow->theme->title_color);
415 canvas->set_font(mwindow->theme->title_font);
416 //printf("ResourcePixmap::draw_title 1 %d\n", total_x + 10);
418 // Justify the text on the left boundary of the edit if it is visible.
419 // Otherwise justify it on the left side of the screen.
420 int text_x = total_x + left_margin;
421 text_x = MAX(left_margin, text_x);
422 canvas->draw_text(text_x,
423 canvas->get_text_ascent(MEDIUMFONT_3D) + 2,
431 // Need to draw one more x
432 void ResourcePixmap::draw_audio_resource(Edit *edit, int x, int w)
435 double asset_over_session = (double)edit->asset->sample_rate /
436 mwindow->edl->session->sample_rate;
438 // Develop strategy for drawing
439 switch(edit->asset->index_status)
441 case INDEX_NOTTESTED:
444 // Disabled. All files have an index.
445 // case INDEX_TOOSMALL:
446 // draw_audio_source(edit, x, w);
451 IndexFile indexfile(mwindow);
452 if(!indexfile.open_index(edit->asset))
454 if(edit->asset->index_zoom >
455 mwindow->edl->local_session->zoom_sample *
458 draw_audio_source(edit, x, w);
461 indexfile.draw_index(this, edit, x, w);
462 indexfile.close_index();
486 void ResourcePixmap::draw_audio_source(Edit *edit, int x, int w)
488 File *source = mwindow->audio_cache->check_out(edit->asset,
493 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
498 double asset_over_session = (double)edit->asset->sample_rate /
499 mwindow->edl->session->sample_rate;
500 int source_len = w * mwindow->edl->local_session->zoom_sample;
501 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
502 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
504 // Single sample zoom
505 if(mwindow->edl->local_session->zoom_sample == 1)
507 int64_t source_start = (int64_t)(((pixmap_x - edit_x + x) *
508 mwindow->edl->local_session->zoom_sample + edit->startsource) *
510 double oldsample, newsample;
511 int total_source_samples = (int)((double)(source_len + 1) *
513 double *buffer = new double[total_source_samples];
515 source->set_audio_position(source_start,
516 edit->asset->sample_rate);
517 source->set_channel(edit->channel);
518 canvas->set_color(mwindow->theme->audio_color);
520 if(!source->read_samples(buffer,
521 total_source_samples,
522 edit->asset->sample_rate))
524 oldsample = newsample = *buffer;
525 for(int x1 = x, x2 = x + w, i = 0;
529 oldsample = newsample;
530 newsample = buffer[(int)(i * asset_over_session)];
531 canvas->draw_line(x1 - 1,
532 (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
534 (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
540 canvas->test_timer();
543 // Multiple sample zoom
551 canvas->set_color(mwindow->theme->audio_color);
552 // Draw each pixel from the cache
555 // Starting sample of pixel relative to asset rate.
556 int64_t source_start = (int64_t)(((pixmap_x - edit_x + x) *
557 mwindow->edl->local_session->zoom_sample + edit->startsource) *
559 int64_t source_end = (int64_t)(((pixmap_x - edit_x + x + 1) *
560 mwindow->edl->local_session->zoom_sample + edit->startsource) *
562 WaveCacheItem *item = mwindow->wave_cache->get_wave(edit->asset->id,
568 y1 = (int)(center_pixel -
569 item->low * mwindow->edl->local_session->zoom_y / 2);
570 y2 = (int)(center_pixel -
571 item->high * mwindow->edl->local_session->zoom_y / 2);
590 mwindow->wave_cache->unlock();
595 canvas->resource_thread->add_wave(this,
607 mwindow->audio_cache->check_in(edit->asset);
612 void ResourcePixmap::draw_wave(int x, double high, double low)
615 if(mwindow->edl->session->show_titles)
616 top_pixel = mwindow->theme->get_image("title_bg_data")->get_h();
617 int center_pixel = mwindow->edl->local_session->zoom_track / 2 + top_pixel;
618 int bottom_pixel = top_pixel + mwindow->edl->local_session->zoom_track;
619 int y1 = (int)(center_pixel -
620 low * mwindow->edl->local_session->zoom_y / 2);
621 int y2 = (int)(center_pixel -
622 high * mwindow->edl->local_session->zoom_y / 2);
623 CLAMP(y1, top_pixel, bottom_pixel);
624 CLAMP(y2, top_pixel, bottom_pixel);
625 canvas->set_color(mwindow->theme->audio_color);
652 void ResourcePixmap::draw_video_resource(Edit *edit,
661 // pixels spanned by a picon
662 int64_t picon_w = Units::round(edit->picon_w());
663 int64_t picon_h = edit->picon_h();
666 // Don't draw video if picon is bigger than edit
667 if(picon_w > edit_w) return;
669 // pixels spanned by a frame
670 double frame_w = edit->frame_w();
672 // Frames spanned by a picon
673 double frames_per_picon = edit->frames_per_picon();
675 // Current pixel relative to pixmap
678 if(mwindow->edl->session->show_titles)
679 y += mwindow->theme->get_image("title_bg_data")->get_h();
680 // Frame in project touched by current pixel
681 int64_t project_frame;
683 // Get first frame touched by x and fix x to start of frame
684 if(frames_per_picon > 1)
686 int picon = Units::to_int64(
687 (double)((int64_t)refresh_x + pixmap_x - edit_x) /
689 x = picon_w * picon + edit_x - pixmap_x;
690 project_frame = Units::to_int64((double)picon * frames_per_picon);
694 project_frame = Units::to_int64((double)((int64_t)refresh_x + pixmap_x - edit_x) /
696 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
700 // Draw only cached frames
701 while(x < refresh_x + refresh_w)
703 int64_t source_frame = project_frame + edit->startsource;
704 VFrame *picon_frame = 0;
707 if((picon_frame = mwindow->frame_cache->get_frame_ptr(source_frame,
709 mwindow->edl->session->frame_rate,
713 edit->asset->id)) != 0)
719 // Set picon thread to display from file
723 canvas->resource_thread->add_picon(this,
728 mwindow->edl->session->frame_rate,
736 draw_vframe(picon_frame,
745 // Unlock the get_frame_ptr command
747 mwindow->frame_cache->unlock();
749 if(frames_per_picon > 1)
751 x += Units::round(picon_w);
752 project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
756 x += Units::round(frame_w);
757 project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
761 canvas->test_timer();
766 void ResourcePixmap::dump()
768 printf("ResourcePixmap %p\n", this);
769 printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);
777 // c-file-style: "linux"