00001 #include "aedit.h"
00002 #include "asset.h"
00003 #include "asset.inc"
00004 #include "cache.h"
00005 #include "clip.h"
00006 #include "colormodels.h"
00007 #include "datatype.h"
00008 #include "edit.h"
00009 #include "edits.h"
00010 #include "edl.h"
00011 #include "edlsession.h"
00012 #include "file.h"
00013 #include "filesystem.h"
00014 #include "framecache.h"
00015 #include "indexfile.h"
00016 #include "language.h"
00017 #include "localsession.h"
00018 #include "mwindow.h"
00019 #include "resourcethread.h"
00020 #include "resourcepixmap.h"
00021 #include "theme.h"
00022 #include "track.h"
00023 #include "trackcanvas.h"
00024 #include "vedit.h"
00025 #include "vframe.h"
00026 #include "wavecache.h"
00027
00028
00029 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
00030 TrackCanvas *canvas,
00031 Edit *edit,
00032 int w,
00033 int h)
00034 : BC_Pixmap(canvas, w, h)
00035 {
00036 reset();
00037
00038 this->mwindow = mwindow;
00039 this->canvas = canvas;
00040 startsource = edit->startsource;
00041 data_type = edit->track->data_type;
00042 source_framerate = edit->asset->frame_rate;
00043 project_framerate = edit->edl->session->frame_rate;
00044 source_samplerate = edit->asset->sample_rate;
00045 project_samplerate = edit->edl->session->sample_rate;
00046 edit_id = edit->id;
00047 }
00048
00049 ResourcePixmap::~ResourcePixmap()
00050 {
00051 }
00052
00053
00054 void ResourcePixmap::reset()
00055 {
00056 edit_x = 0;
00057 pixmap_x = 0;
00058 pixmap_w = 0;
00059 pixmap_h = 0;
00060 zoom_sample = 0;
00061 zoom_track = 0;
00062 zoom_y = 0;
00063 visible = 1;
00064 }
00065
00066 void ResourcePixmap::resize(int w, int h)
00067 {
00068 int new_w = (w > get_w()) ? w : get_w();
00069 int new_h = (h > get_h()) ? h : get_h();
00070
00071 BC_Pixmap::resize(new_w, new_h);
00072 }
00073
00074
00075 void ResourcePixmap::draw_data(Edit *edit,
00076 int64_t edit_x,
00077 int64_t edit_w,
00078 int64_t pixmap_x,
00079 int64_t pixmap_w,
00080 int64_t pixmap_h,
00081 int mode,
00082 int indexes_only)
00083 {
00084
00085
00086 int refresh_x = 0;
00087 int refresh_w = 0;
00088
00089
00090 if(mode == 3) return;
00091
00092 int y = 0;
00093 if(mwindow->edl->session->show_titles) y += mwindow->theme->get_image("title_bg_data")->get_h();
00094 Track *track = edit->edits->track;
00095
00096
00097
00098 int need_redraw = 0;
00099 int64_t index_zoom = 0;
00100 if(indexes_only)
00101 {
00102 IndexFile indexfile(mwindow);
00103 if(!indexfile.open_index(edit->asset))
00104 {
00105 index_zoom = edit->asset->index_zoom;
00106 indexfile.close_index();
00107 }
00108
00109 if(index_zoom)
00110 {
00111 if(data_type == TRACK_AUDIO)
00112 {
00113 double asset_over_session = (double)edit->asset->sample_rate /
00114 mwindow->edl->session->sample_rate;
00115 asset_over_session;
00116 if(index_zoom <= mwindow->edl->local_session->zoom_sample *
00117 asset_over_session)
00118 need_redraw = 1;
00119 }
00120 }
00121
00122 if(!need_redraw)
00123 return;
00124 }
00125
00126
00127
00128 if(edit->startsource != this->startsource ||
00129
00130 (data_type == TRACK_AUDIO
00131 ) ||
00132 (data_type == TRACK_VIDEO
00133 ) ||
00134 mwindow->edl->session->sample_rate != project_samplerate ||
00135 mwindow->edl->session->frame_rate != project_framerate ||
00136 mwindow->edl->local_session->zoom_sample != zoom_sample ||
00137 mwindow->edl->local_session->zoom_track != zoom_track ||
00138 this->pixmap_h != pixmap_h ||
00139 (data_type == TRACK_AUDIO &&
00140 mwindow->edl->local_session->zoom_y != zoom_y) ||
00141 (mode == 2) ||
00142 need_redraw)
00143 {
00144
00145 refresh_x = 0;
00146 refresh_w = pixmap_w;
00147 }
00148 else
00149 {
00150
00151 if(pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w)
00152 {
00153 refresh_w = this->edit_x - edit_x;
00154 refresh_x = this->pixmap_w - refresh_w;
00155
00156
00157 if(refresh_w > this->pixmap_w)
00158 {
00159 refresh_w = this->pixmap_w;
00160 refresh_x = 0;
00161 }
00162 else
00163 {
00164 copy_area(refresh_w,
00165 y,
00166 refresh_x,
00167 mwindow->edl->local_session->zoom_track,
00168 0,
00169 y);
00170 }
00171 }
00172 else
00173
00174 if(pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w)
00175 {
00176 refresh_x = 0;
00177 refresh_w = edit_x - this->edit_x;
00178
00179
00180 if(refresh_w > this->pixmap_w)
00181 {
00182 refresh_w = this->pixmap_w;
00183 }
00184 else
00185 {
00186 copy_area(0,
00187 y,
00188 this->pixmap_w - refresh_w,
00189 mwindow->edl->local_session->zoom_track,
00190 refresh_w,
00191 y);
00192 }
00193 }
00194 else
00195
00196 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x &&
00197 this->edit_x + edit_w > this->pixmap_x + this->pixmap_w)
00198 {
00199 refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
00200 refresh_x = pixmap_w - refresh_w;
00201
00202 if(refresh_w >= pixmap_w)
00203 {
00204 refresh_x = 0;
00205 refresh_w = pixmap_w;
00206 }
00207 else
00208 {
00209 copy_area(this->edit_x - edit_x,
00210 y,
00211 pixmap_w - refresh_w,
00212 mwindow->edl->local_session->zoom_track,
00213 0,
00214 y);
00215 }
00216 }
00217 else
00218
00219 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x)
00220 {
00221 refresh_x = 0;
00222 refresh_w = 0;
00223
00224 copy_area(this->pixmap_w - pixmap_w,
00225 y,
00226 pixmap_w,
00227 mwindow->edl->local_session->zoom_track,
00228 0,
00229 y);
00230 }
00231 else
00232
00233 if(edit_x >= 0 && this->edit_x < 0)
00234 {
00235 refresh_x = 0;
00236 refresh_w = -this->edit_x;
00237
00238 if(refresh_w > pixmap_w)
00239 {
00240 refresh_w = pixmap_w;
00241 }
00242 else
00243 {
00244 copy_area(0,
00245 y,
00246 this->pixmap_w,
00247 mwindow->edl->local_session->zoom_track,
00248 refresh_w,
00249 y);
00250 }
00251 }
00252 else
00253
00254 if(pixmap_w < this->pixmap_w && edit_x > this->edit_x)
00255 {
00256 refresh_x = 0;
00257 refresh_w = 0;
00258 }
00259 else
00260
00261 if(pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0)
00262 {
00263 refresh_w = pixmap_w - (edit_x + this->pixmap_w);
00264 refresh_x = pixmap_w - refresh_w;
00265
00266
00267 if(refresh_w > pixmap_w)
00268 {
00269 refresh_w = pixmap_w;
00270 refresh_x = 0;
00271 }
00272 else
00273 {
00274 copy_area(-edit_x,
00275 y,
00276 refresh_x,
00277 mwindow->edl->local_session->zoom_track,
00278 0,
00279 y);
00280 }
00281 }
00282 else
00283
00284 if(pixmap_w > this->pixmap_w && edit_x <= this->edit_x)
00285 {
00286 refresh_w = pixmap_w - this->pixmap_w;
00287 refresh_x = pixmap_w - refresh_w;
00288 }
00289 else
00290
00291 if(pixmap_w > this->pixmap_w && edit_x > this->edit_x)
00292 {
00293 refresh_x = 0;
00294 refresh_w = edit_x - this->edit_x;
00295
00296
00297 if(refresh_w > this->pixmap_w)
00298 {
00299 refresh_w = pixmap_w;
00300 refresh_x = 0;
00301 }
00302
00303 else
00304 {
00305 copy_area(0,
00306 y,
00307 this->pixmap_w,
00308 mwindow->edl->local_session->zoom_track,
00309 refresh_w,
00310 y);
00311 }
00312 }
00313 }
00314
00315
00316 this->edit_id = edit->id;
00317 this->startsource = edit->startsource;
00318 this->source_framerate = edit->asset->frame_rate;
00319 this->source_samplerate = edit->asset->sample_rate;
00320 this->project_framerate = edit->edl->session->frame_rate;
00321 this->project_samplerate = edit->edl->session->sample_rate;
00322 this->edit_x = edit_x;
00323 this->pixmap_x = pixmap_x;
00324 this->pixmap_w = pixmap_w;
00325 this->pixmap_h = pixmap_h;
00326 this->zoom_sample = mwindow->edl->local_session->zoom_sample;
00327 this->zoom_track = mwindow->edl->local_session->zoom_track;
00328 this->zoom_y = mwindow->edl->local_session->zoom_y;
00329
00330
00331
00332
00333 if(refresh_w > 0)
00334 mwindow->theme->draw_resource_bg(canvas,
00335 this,
00336 edit_x,
00337 edit_w,
00338 pixmap_x,
00339 refresh_x,
00340 y,
00341 refresh_x + refresh_w,
00342 mwindow->edl->local_session->zoom_track + y);
00343
00344
00345
00346
00347 if(track->draw)
00348 {
00349 switch(track->data_type)
00350 {
00351 case TRACK_AUDIO:
00352 draw_audio_resource(edit, refresh_x, refresh_w);
00353 break;
00354
00355 case TRACK_VIDEO:
00356 draw_video_resource(edit,
00357 edit_x,
00358 edit_w,
00359 pixmap_x,
00360 pixmap_w,
00361 refresh_x,
00362 refresh_w,
00363 mode);
00364 break;
00365 }
00366 }
00367
00368
00369 if(mwindow->edl->session->show_titles)
00370 draw_title(edit, edit_x, edit_w, pixmap_x, pixmap_w);
00371 }
00372
00373 void ResourcePixmap::draw_title(Edit *edit,
00374 int64_t edit_x,
00375 int64_t edit_w,
00376 int64_t pixmap_x,
00377 int64_t pixmap_w)
00378 {
00379
00380 int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
00381 int64_t x = total_x, w = total_w;
00382 int left_margin = 10;
00383
00384 if(x < 0)
00385 {
00386 w -= -x;
00387 x = 0;
00388 }
00389 if(w > pixmap_w) w -= w - pixmap_w;
00390
00391 canvas->draw_3segmenth(x,
00392 0,
00393 w,
00394 total_x,
00395 total_w,
00396 mwindow->theme->get_image("title_bg_data"),
00397 this);
00398
00399 if(total_x > -BC_INFINITY)
00400 {
00401 char title[BCTEXTLEN], channel[BCTEXTLEN];
00402 FileSystem fs;
00403
00404 if(edit->user_title[0])
00405 strcpy(title, edit->user_title);
00406 else
00407 {
00408 fs.extract_name(title, edit->asset->path);
00409
00410 sprintf(channel, " #%d", edit->channel + 1);
00411 strcat(title, channel);
00412 }
00413
00414 canvas->set_color(mwindow->theme->title_color);
00415 canvas->set_font(mwindow->theme->title_font);
00416
00417
00418
00419
00420 int text_x = total_x + left_margin;
00421 text_x = MAX(left_margin, text_x);
00422 canvas->draw_text(text_x,
00423 canvas->get_text_ascent(MEDIUMFONT_3D) + 2,
00424 title,
00425 strlen(title),
00426 this);
00427 }
00428 }
00429
00430
00431
00432 void ResourcePixmap::draw_audio_resource(Edit *edit, int x, int w)
00433 {
00434 if(w <= 0) return;
00435 double asset_over_session = (double)edit->asset->sample_rate /
00436 mwindow->edl->session->sample_rate;
00437
00438
00439 switch(edit->asset->index_status)
00440 {
00441 case INDEX_NOTTESTED:
00442 return;
00443 break;
00444
00445
00446
00447
00448 case INDEX_BUILDING:
00449 case INDEX_READY:
00450 {
00451 IndexFile indexfile(mwindow);
00452 if(!indexfile.open_index(edit->asset))
00453 {
00454 if(edit->asset->index_zoom >
00455 mwindow->edl->local_session->zoom_sample *
00456 asset_over_session)
00457 {
00458 draw_audio_source(edit, x, w);
00459 }
00460 else
00461 indexfile.draw_index(this, edit, x, w);
00462 indexfile.close_index();
00463 }
00464 break;
00465 }
00466 }
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 void ResourcePixmap::draw_audio_source(Edit *edit, int x, int w)
00487 {
00488 File *source = mwindow->audio_cache->check_out(edit->asset,
00489 mwindow->edl);
00490
00491 if(!source)
00492 {
00493 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
00494 return;
00495 }
00496
00497 w++;
00498 double asset_over_session = (double)edit->asset->sample_rate /
00499 mwindow->edl->session->sample_rate;
00500 int source_len = w * mwindow->edl->local_session->zoom_sample;
00501 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
00502 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
00503
00504
00505 if(mwindow->edl->local_session->zoom_sample == 1)
00506 {
00507 int64_t source_start = (int64_t)(((pixmap_x - edit_x + x) *
00508 mwindow->edl->local_session->zoom_sample + edit->startsource) *
00509 asset_over_session);
00510 double oldsample, newsample;
00511 int total_source_samples = (int)((double)(source_len + 1) *
00512 asset_over_session);
00513 double *buffer = new double[total_source_samples];
00514
00515 source->set_audio_position(source_start,
00516 edit->asset->sample_rate);
00517 source->set_channel(edit->channel);
00518 canvas->set_color(mwindow->theme->audio_color);
00519
00520 if(!source->read_samples(buffer,
00521 total_source_samples,
00522 edit->asset->sample_rate))
00523 {
00524 oldsample = newsample = *buffer;
00525 for(int x1 = x, x2 = x + w, i = 0;
00526 x1 < x2;
00527 x1++, i++)
00528 {
00529 oldsample = newsample;
00530 newsample = buffer[(int)(i * asset_over_session)];
00531 canvas->draw_line(x1 - 1,
00532 (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
00533 x1,
00534 (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
00535 this);
00536 }
00537 }
00538
00539 delete [] buffer;
00540 canvas->test_timer();
00541 }
00542 else
00543
00544 {
00545 int first_pixel = 1;
00546 int prev_y1 = -1;
00547 int prev_y2 = -1;
00548 int y1;
00549 int y2;
00550
00551 canvas->set_color(mwindow->theme->audio_color);
00552
00553 while(x < w)
00554 {
00555
00556 int64_t source_start = (int64_t)(((pixmap_x - edit_x + x) *
00557 mwindow->edl->local_session->zoom_sample + edit->startsource) *
00558 asset_over_session);
00559 int64_t source_end = (int64_t)(((pixmap_x - edit_x + x + 1) *
00560 mwindow->edl->local_session->zoom_sample + edit->startsource) *
00561 asset_over_session);
00562 WaveCacheItem *item = mwindow->wave_cache->get_wave(edit->asset->id,
00563 edit->channel,
00564 source_start,
00565 source_end);
00566 if(item)
00567 {
00568 y1 = (int)(center_pixel -
00569 item->low * mwindow->edl->local_session->zoom_y / 2);
00570 y2 = (int)(center_pixel -
00571 item->high * mwindow->edl->local_session->zoom_y / 2);
00572 if(first_pixel)
00573 {
00574 canvas->draw_line(x,
00575 y1,
00576 x,
00577 y2,
00578 this);
00579 first_pixel = 0;
00580 }
00581 else
00582 canvas->draw_line(x,
00583 MIN(y1, prev_y2),
00584 x,
00585 MAX(y2, prev_y1),
00586 this);
00587 prev_y1 = y1;
00588 prev_y2 = y2;
00589 first_pixel = 0;
00590 mwindow->wave_cache->unlock();
00591 }
00592 else
00593 {
00594 first_pixel = 1;
00595 canvas->resource_thread->add_wave(this,
00596 edit->asset,
00597 x,
00598 edit->channel,
00599 source_start,
00600 source_end);
00601 }
00602
00603 x++;
00604 }
00605 }
00606
00607 mwindow->audio_cache->check_in(edit->asset);
00608 }
00609
00610
00611
00612 void ResourcePixmap::draw_wave(int x, double high, double low)
00613 {
00614 int top_pixel = 0;
00615 if(mwindow->edl->session->show_titles)
00616 top_pixel = mwindow->theme->get_image("title_bg_data")->get_h();
00617 int center_pixel = mwindow->edl->local_session->zoom_track / 2 + top_pixel;
00618 int bottom_pixel = top_pixel + mwindow->edl->local_session->zoom_track;
00619 int y1 = (int)(center_pixel -
00620 low * mwindow->edl->local_session->zoom_y / 2);
00621 int y2 = (int)(center_pixel -
00622 high * mwindow->edl->local_session->zoom_y / 2);
00623 CLAMP(y1, top_pixel, bottom_pixel);
00624 CLAMP(y2, top_pixel, bottom_pixel);
00625 canvas->set_color(mwindow->theme->audio_color);
00626 canvas->draw_line(x,
00627 y1,
00628 x,
00629 y2,
00630 this);
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 void ResourcePixmap::draw_video_resource(Edit *edit,
00653 int64_t edit_x,
00654 int64_t edit_w,
00655 int64_t pixmap_x,
00656 int64_t pixmap_w,
00657 int refresh_x,
00658 int refresh_w,
00659 int mode)
00660 {
00661
00662 int64_t picon_w = Units::round(edit->picon_w());
00663 int64_t picon_h = edit->picon_h();
00664
00665
00666
00667 if(picon_w > edit_w) return;
00668
00669
00670 double frame_w = edit->frame_w();
00671
00672
00673 double frames_per_picon = edit->frames_per_picon();
00674
00675
00676 int x = 0;
00677 int y = 0;
00678 if(mwindow->edl->session->show_titles)
00679 y += mwindow->theme->get_image("title_bg_data")->get_h();
00680
00681 int64_t project_frame;
00682
00683
00684 if(frames_per_picon > 1)
00685 {
00686 int picon = Units::to_int64(
00687 (double)((int64_t)refresh_x + pixmap_x - edit_x) /
00688 picon_w);
00689 x = picon_w * picon + edit_x - pixmap_x;
00690 project_frame = Units::to_int64((double)picon * frames_per_picon);
00691 }
00692 else
00693 {
00694 project_frame = Units::to_int64((double)((int64_t)refresh_x + pixmap_x - edit_x) /
00695 frame_w);
00696 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
00697 }
00698
00699
00700
00701 while(x < refresh_x + refresh_w)
00702 {
00703 int64_t source_frame = project_frame + edit->startsource;
00704 VFrame *picon_frame = 0;
00705 int use_cache = 0;
00706
00707 if((picon_frame = mwindow->frame_cache->get_frame_ptr(source_frame,
00708 edit->channel,
00709 mwindow->edl->session->frame_rate,
00710 BC_RGB888,
00711 picon_w,
00712 picon_h,
00713 edit->asset->id)) != 0)
00714 {
00715 use_cache = 1;
00716 }
00717 else
00718 {
00719
00720 if(mode != 3)
00721 {
00722
00723 canvas->resource_thread->add_picon(this,
00724 x,
00725 y,
00726 picon_w,
00727 picon_h,
00728 mwindow->edl->session->frame_rate,
00729 source_frame,
00730 edit->channel,
00731 edit->asset);
00732 }
00733 }
00734
00735 if(picon_frame)
00736 draw_vframe(picon_frame,
00737 x,
00738 y,
00739 picon_w,
00740 picon_h,
00741 0,
00742 0);
00743
00744
00745
00746 if(use_cache)
00747 mwindow->frame_cache->unlock();
00748
00749 if(frames_per_picon > 1)
00750 {
00751 x += Units::round(picon_w);
00752 project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
00753 }
00754 else
00755 {
00756 x += Units::round(frame_w);
00757 project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
00758 }
00759
00760
00761 canvas->test_timer();
00762 }
00763 }
00764
00765
00766 void ResourcePixmap::dump()
00767 {
00768 printf("ResourcePixmap %p\n", this);
00769 printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);
00770 }
00771
00772
00773