r858: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / resourcepixmap.C
blobf67b7530492dd6e30dda2c98422bc1eb4cb5802a
1 #include "aedit.h"
2 #include "asset.h"
3 #include "asset.inc"
4 #include "cache.h"
5 #include "clip.h"
6 #include "colormodels.h"
7 #include "datatype.h"
8 #include "edit.h"
9 #include "edits.h"
10 #include "edl.h"
11 #include "edlsession.h"
12 #include "file.h"
13 #include "filesystem.h"
14 #include "framecache.h"
15 #include "indexfile.h"
16 #include "language.h"
17 #include "localsession.h"
18 #include "mwindow.h"
19 #include "resourcepixmap.h"
20 #include "theme.h"
21 #include "track.h"
22 #include "trackcanvas.h"
23 #include "vedit.h"
24 #include "vframe.h"
27 ResourcePixmap::ResourcePixmap(MWindow *mwindow, 
28         TrackCanvas *canvas, 
29         Edit *edit, 
30         int w, 
31         int h)
32  : BC_Pixmap(canvas, w, h)
34         reset();
36         this->mwindow = mwindow;
37         this->canvas = canvas;
38         startsource = edit->startsource;
39         data_type = edit->track->data_type;
40         source_framerate = edit->asset->frame_rate;
41         project_framerate = edit->edl->session->frame_rate;
42         source_samplerate = edit->asset->sample_rate;
43         project_samplerate = edit->edl->session->sample_rate;
44         edit_id = edit->id;
47 ResourcePixmap::~ResourcePixmap()
52 void ResourcePixmap::reset()
54         edit_x = 0;
55         pixmap_x = 0;
56         pixmap_w = 0;
57         pixmap_h = 0;
58         zoom_sample = 0;
59         zoom_track = 0;
60         zoom_y = 0;
61         visible = 1;
63         
64 void ResourcePixmap::resize(int w, int h)
66         int new_w = (w > get_w()) ? w : get_w();
67         int new_h = (h > get_h()) ? h : get_h();
69         BC_Pixmap::resize(new_w, new_h);
73 void ResourcePixmap::draw_data(Edit *edit,
74         int64_t edit_x,
75         int64_t edit_w, 
76         int64_t pixmap_x, 
77         int64_t pixmap_w,
78         int64_t pixmap_h,
79         int force,
80         int indexes_only)
82 // Get new areas to fill in relative to pixmap
83 // Area to redraw relative to pixmap
84         int refresh_x = 0;
85         int refresh_w = 0;
89         int y = 0;
90         if(mwindow->edl->session->show_titles) y += mwindow->theme->get_image("title_bg_data")->get_h();
91         Track *track = edit->edits->track;
94 // If index can't be drawn, don't do anything.
95         int need_redraw = 0;
96         int64_t index_zoom = 0;
97         if(indexes_only)
98         {
99                 IndexFile indexfile(mwindow);
100                 if(!indexfile.open_index(edit->asset))
101                 {
102                         index_zoom = edit->asset->index_zoom;
103                         indexfile.close_index();
104                 }
106                 if(index_zoom)
107                 {
108                         if(data_type == TRACK_AUDIO)
109                         {
110                                 double asset_over_session = (double)edit->asset->sample_rate / 
111                                         mwindow->edl->session->sample_rate;
112                                         asset_over_session;
113                                 if(index_zoom <= mwindow->edl->local_session->zoom_sample *
114                                         asset_over_session)
115                                         need_redraw = 1;
116                         }
117                 }
119                 if(!need_redraw)
120                         return;
121         }
124 // Redraw everything
125         if(edit->startsource != this->startsource ||
126                 (data_type == TRACK_AUDIO && 
127                         edit->asset->sample_rate != source_samplerate) ||
128                 (data_type == TRACK_VIDEO && 
129                         !EQUIV(edit->asset->frame_rate, source_framerate)) ||
130                 mwindow->edl->session->sample_rate != project_samplerate ||
131                 mwindow->edl->session->frame_rate != project_framerate ||
132                 mwindow->edl->local_session->zoom_sample != zoom_sample || 
133                 mwindow->edl->local_session->zoom_track != zoom_track ||
134                 this->pixmap_h != pixmap_h ||
135                 (data_type == TRACK_AUDIO && 
136                         mwindow->edl->local_session->zoom_y != zoom_y) ||
137                 force ||
138                 need_redraw)
139         {
140 // Shouldn't draw at all if zoomed in below index zoom.
141                 refresh_x = 0;
142                 refresh_w = pixmap_w;
143         }
144         else
145         {
146 // Start translated right
147                 if(pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w)
148                 {
149                         refresh_w = this->edit_x - edit_x;
150                         refresh_x = this->pixmap_w - refresh_w;
152 // Moved completely off the pixmap
153                         if(refresh_w > this->pixmap_w)
154                         {
155                                 refresh_w = this->pixmap_w;
156                                 refresh_x = 0;
157                         }
158                         else
159                         {
160                                 copy_area(refresh_w, 
161                                         y, 
162                                         refresh_x, 
163                                         mwindow->edl->local_session->zoom_track, 
164                                         0, 
165                                         y);
166                         }
167                 }
168                 else
169 // Start translated left
170                 if(pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w)
171                 {
172                         refresh_x = 0;
173                         refresh_w = edit_x - this->edit_x;
175 // Moved completely off the pixmap
176                         if(refresh_w > this->pixmap_w)
177                         {
178                                 refresh_w = this->pixmap_w;
179                         }
180                         else
181                         {
182                                 copy_area(0, 
183                                         y, 
184                                         this->pixmap_w - refresh_w, 
185                                         mwindow->edl->local_session->zoom_track, 
186                                         refresh_w, 
187                                         y);
188                         }
189                 }
190                 else
191 // Start translated right and pixmap came off of right side
192                 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x && 
193                         this->edit_x + edit_w > this->pixmap_x + this->pixmap_w)
194                 {
195                         refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
196                         refresh_x = pixmap_w - refresh_w;
197                         
198                         if(refresh_w >= pixmap_w)
199                         {
200                                 refresh_x = 0;
201                                 refresh_w = pixmap_w;
202                         }
203                         else
204                         {
205                                 copy_area(this->edit_x - edit_x, 
206                                         y, 
207                                         pixmap_w - refresh_w, 
208                                         mwindow->edl->local_session->zoom_track, 
209                                         0, 
210                                         y);
211                         }
212                 }
213                 else
214 // Start translated right and reduced in size on the right.
215                 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x)
216                 {
217                         refresh_x = 0;
218                         refresh_w = 0;
220                         copy_area(this->pixmap_w - pixmap_w, 
221                                 y, 
222                                 pixmap_w, 
223                                 mwindow->edl->local_session->zoom_track, 
224                                 0, 
225                                 y);
226                 }
227                 else
228 // Start translated left and pixmap came off left side
229                 if(edit_x >= 0 && this->edit_x < 0)
230                 {
231                         refresh_x = 0;
232                         refresh_w = -this->edit_x;
234                         if(refresh_w > pixmap_w)
235                         {
236                                 refresh_w = pixmap_w;
237                         }
238                         else
239                         {
240                                 copy_area(0, 
241                                                 y, 
242                                                 this->pixmap_w, 
243                                                 mwindow->edl->local_session->zoom_track, 
244                                                 refresh_w, 
245                                                 y);
246                         }
247                 }
248                 else
249 // Start translated left and reduced in size on the right
250                 if(pixmap_w < this->pixmap_w && edit_x > this->edit_x)
251                 {
252                         refresh_x = 0;
253                         refresh_w = 0;
254                 }
255                 else
256 // Start translated right and left went into left side.
257                 if(pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0)
258                 {
259                         refresh_w = pixmap_w - (edit_x + this->pixmap_w);
260                         refresh_x = pixmap_w - refresh_w;
262 // Moved completely off new pixmap
263                         if(refresh_w > pixmap_w)
264                         {
265                                 refresh_w = pixmap_w;
266                                 refresh_x = 0;
267                         }
268                         else
269                         {
270                                 copy_area(-edit_x, 
271                                         y,
272                                         refresh_x,
273                                         mwindow->edl->local_session->zoom_track,
274                                         0,
275                                         y);
276                         }
277                 }
278                 else
279 // Start translated right and increased in size on the right
280                 if(pixmap_w > this->pixmap_w && edit_x <= this->edit_x)
281                 {
282                         refresh_w = pixmap_w - this->pixmap_w;
283                         refresh_x = pixmap_w - refresh_w;
284                 }
285                 else
286 // Start translated left and increased in size on the right
287                 if(pixmap_w > this->pixmap_w && edit_x > this->edit_x)
288                 {
289                         refresh_x = 0;
290                         refresh_w = edit_x - this->edit_x;
292 // Moved completely off new pixmap
293                         if(refresh_w > this->pixmap_w)
294                         {
295                                 refresh_w = pixmap_w;
296                                 refresh_x = 0;
297                         }
298 // Shift and insert
299                         else
300                         {
301                                 copy_area(0, 
302                                         y,
303                                         this->pixmap_w,
304                                         mwindow->edl->local_session->zoom_track,
305                                         refresh_w,
306                                         y);
307                         }
308                 }
309         }
311 // Update pixmap settings
312         this->edit_id = edit->id;
313         this->startsource = edit->startsource;
314         this->source_framerate = edit->asset->frame_rate;
315         this->source_samplerate = edit->asset->sample_rate;
316         this->project_framerate = edit->edl->session->frame_rate;
317         this->project_samplerate = edit->edl->session->sample_rate;
318         this->edit_x = edit_x;
319         this->pixmap_x = pixmap_x;
320         this->pixmap_w = pixmap_w;
321         this->pixmap_h = pixmap_h;
322         this->zoom_sample = mwindow->edl->local_session->zoom_sample;
323         this->zoom_track = mwindow->edl->local_session->zoom_track;
324         this->zoom_y = mwindow->edl->local_session->zoom_y;
328 // Draw in new background
329         if(refresh_w > 0)
330                 mwindow->theme->draw_resource_bg(canvas,
331                         this, 
332                         edit_x,
333                         edit_w,
334                         pixmap_x,
335                         refresh_x, 
336                         y,
337                         refresh_x + refresh_w,
338                         mwindow->edl->local_session->zoom_track + y);
339 //printf("ResourcePixmap::draw_data 70\n");
342 // Draw media
343         if(track->draw)
344         {
345                 switch(track->data_type)
346                 {
347                         case TRACK_AUDIO:
348                                 draw_audio_resource(edit, refresh_x, refresh_w);
349                                 break;
351                         case TRACK_VIDEO:
352                                 draw_video_resource(edit, 
353                                         edit_x, 
354                                         edit_w, 
355                                         pixmap_x,
356                                         pixmap_w,
357                                         refresh_x, 
358                                         refresh_w);
359                                 break;
360                 }
361         }
363 // Draw title
364         if(mwindow->edl->session->show_titles)
365                 draw_title(edit, edit_x, edit_w, pixmap_x, pixmap_w);
368 void ResourcePixmap::draw_title(Edit *edit,
369         int64_t edit_x, 
370         int64_t edit_w, 
371         int64_t pixmap_x, 
372         int64_t pixmap_w)
374 // coords relative to pixmap
375         int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
376         int64_t x = total_x, w = total_w;
377         int left_margin = 10;
379         if(x < 0) 
380         {
381                 w -= -x;
382                 x = 0;
383         }
384         if(w > pixmap_w) w -= w - pixmap_w;
386         canvas->draw_3segmenth(x, 
387                 0, 
388                 w, 
389                 total_x,
390                 total_w,
391                 mwindow->theme->get_image("title_bg_data"),
392                 this);
394         if(total_x > -BC_INFINITY)
395         {
396                 char title[BCTEXTLEN], channel[BCTEXTLEN];
397                 FileSystem fs;
399                 if(edit->user_title[0])
400                         strcpy(title, edit->user_title);
401                 else
402                 {
403                         fs.extract_name(title, edit->asset->path);
405                         sprintf(channel, " #%d", edit->channel + 1);
406                         strcat(title, channel);
407                 }
409                 canvas->set_color(mwindow->theme->title_color);
410                 canvas->set_font(mwindow->theme->title_font);
411 //printf("ResourcePixmap::draw_title 1 %d\n", total_x + 10);
412                 
413 // Justify the text on the left boundary of the edit if it is visible.
414 // Otherwise justify it on the left side of the screen.
415                 int text_x = total_x + left_margin;
416                 text_x = MAX(left_margin, text_x);
417                 canvas->draw_text(text_x, 
418                         canvas->get_text_ascent(MEDIUMFONT_3D) + 2, 
419                         title,
420                         strlen(title),
421                         this);
422         }
426 // Need to draw one more x
427 void ResourcePixmap::draw_audio_resource(Edit *edit, int x, int w)
429         if(w <= 0) return;
430         double asset_over_session = (double)edit->asset->sample_rate / 
431                 mwindow->edl->session->sample_rate;
433 // Develop strategy for drawing
434         switch(edit->asset->index_status)
435         {
436                 case INDEX_NOTTESTED:
437                         return;
438                         break;
439 // Disabled.  Always draw from index.
440                 case INDEX_TOOSMALL:
441                         draw_audio_source(edit, x, w);
442                         break;
443                 case INDEX_BUILDING:
444                 case INDEX_READY:
445                 {
446                         IndexFile indexfile(mwindow);
447                         if(!indexfile.open_index(edit->asset))
448                         {
449                                 if(edit->asset->index_zoom > 
450                                                 mwindow->edl->local_session->zoom_sample * 
451                                                 asset_over_session)
452                                 {
453                                         draw_audio_source(edit, x, w);
454                                 }
455                                 else
456                                         indexfile.draw_index(this, edit, x, w);
457                                 indexfile.close_index();
458                         }
459                         break;
460                 }
461         }
481 void ResourcePixmap::draw_audio_source(Edit *edit, int x, int w)
483         File *source = mwindow->audio_cache->check_out(edit->asset,
484                 mwindow->edl);
486         if(!source)
487         {
488                 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
489                 return;
490         }
492         w++;
493         int source_start = (pixmap_x - edit_x + x) * mwindow->edl->local_session->zoom_sample + edit->startsource;
494         double asset_over_session = (double)edit->asset->sample_rate / 
495                 mwindow->edl->session->sample_rate;
496         int source_len = w * mwindow->edl->local_session->zoom_sample;
497         int center_pixel = mwindow->edl->local_session->zoom_track / 2;
498         if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
500 // Single sample zoom
501         if(mwindow->edl->local_session->zoom_sample == 1)
502         {
503                 double oldsample, newsample;
504                 int total_source_samples = (int)((double)(source_len + 1) * 
505                         asset_over_session);
506                 double *buffer = new double[total_source_samples];
508                 source->set_audio_position((int)((double)source_start *
509                                 asset_over_session), 
510                         edit->asset->sample_rate);
511                 source->set_channel(edit->channel);
512                 canvas->set_color(mwindow->theme->audio_color);
514                 if(!source->read_samples(buffer, 
515                         total_source_samples, 
516                         edit->asset->sample_rate))
517                 {
518                         oldsample = newsample = *buffer;
519                         for(int x1 = x, x2 = x + w, i = 0; 
520                                 x1 < x2; 
521                                 x1++, i++)
522                         {
523                                 oldsample = newsample;
524                                 newsample = buffer[(int)(i * asset_over_session)];
525                                 canvas->draw_line(x1 - 1, 
526                                         (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
527                                         x1,
528                                         (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
529                                         this);
530                         }
531                 }
533                 delete [] buffer;
534                 canvas->test_timer();
535         }
536         else
537 // Multiple sample zoom
538         {
539                 int fragmentsize;
540                 int buffersize = fragmentsize = 65536;
541                 double *buffer = new double[buffersize + 1];
542                 double highsample, lowsample;
543                 float sample_of_pixel = 0;
544                 int total_source_samples = (int)(source_len * 
545                         asset_over_session);
546                 double asset_samples_per_pixel = 
547                         mwindow->edl->local_session->zoom_sample *
548                         asset_over_session;
549                 int first_pixel = 1;
550                 int prev_y1 = -1;
551                 int prev_y2 = -1;
552                 int y1;
553                 int y2;
554                 double x_double = x;
556                 source->set_audio_position((int)(source_start * asset_over_session), 
557                         edit->asset->sample_rate);
558                 source->set_channel(edit->channel);
559                 canvas->set_color(mwindow->theme->audio_color);
561                 for(int source_sample = 0; 
562                         source_sample < total_source_samples; 
563                         source_sample += buffersize)
564                 {
565                         fragmentsize = buffersize;
566                         if(total_source_samples - source_sample < buffersize)
567                                 fragmentsize = total_source_samples - source_sample;
569                         if(source_sample == 0)
570                         {
571                                 highsample = buffer[0];
572                                 lowsample = buffer[0];
573                         }
575                         if(!source->read_samples(buffer, 
576                                 fragmentsize, 
577                                 edit->asset->sample_rate))
578                         {
581 // Draw samples for this buffer
582                                 for(int bufferposition = 0; 
583                                         bufferposition < fragmentsize; 
584                                         bufferposition++)
585                                 {
586 // Replicate
587                                         if(asset_samples_per_pixel < 1)
588                                         {
589                                                 int x1 = (int)x_double;
590                                                 x_double += (double)1 / asset_samples_per_pixel;
591                                                 int x2 = (int)x_double;
593                                                 y1 = (int)(center_pixel - 
594                                                                 buffer[bufferposition] * 
595                                                                 mwindow->edl->local_session->zoom_y / 
596                                                                 2);
597                                                 if(first_pixel)
598                                                 {
599                                                         canvas->draw_line(x1, 
600                                                                 y1,
601                                                                 x2,
602                                                                 y1,
603                                                                 this);
604                                                         first_pixel = 0;
605                                                 }
606                                                 else
607                                                         canvas->draw_line(x1, 
608                                                                 prev_y1,
609                                                                 x2,
610                                                                 y1,
611                                                                 this);
612                                                 prev_y1 = y1;
613                                         }
614                                         else
615                                         if(asset_samples_per_pixel >= 1 &&
616                                                 sample_of_pixel >= asset_samples_per_pixel)
617                                         {
618 // Draw column and reset
619                                                 y1 = (int)(center_pixel - 
620                                                         highsample * 
621                                                         mwindow->edl->local_session->zoom_y / 
622                                                         2);
623                                                 y2 = (int)(center_pixel - 
624                                                         lowsample * 
625                                                         mwindow->edl->local_session->zoom_y / 
626                                                         2);
628                                                 int current_y1;
629                                                 int current_y2;
630                                                 if(first_pixel)
631                                                 {
632                                                         canvas->draw_line(x, 
633                                                                 y1,
634                                                                 x,
635                                                                 y2,
636                                                                 this);
637                                                         first_pixel = 0;
638                                                 }
639                                                 else
640                                                         canvas->draw_line(x, 
641                                                                 MIN(y1, prev_y2),
642                                                                 x,
643                                                                 MAX(y2, prev_y1),
644                                                                 this);
645                                                 sample_of_pixel -= asset_samples_per_pixel;
646                                                 x++;
647                                                 lowsample = highsample = buffer[bufferposition];
648                                                 prev_y1 = y1;
649                                                 prev_y2 = y2;
650                                         }
652                                         if(sample_of_pixel >= 1)
653                                         {
654 // update lowsample and highsample
655                                                 if(buffer[bufferposition] < lowsample) 
656                                                         lowsample = buffer[bufferposition];
657                                                 else 
658                                                 if(buffer[bufferposition] > highsample) 
659                                                         highsample = buffer[bufferposition];
660                                         }
663                                         sample_of_pixel++;
664                                 }
670                         }
673                         canvas->test_timer();
674                 }
675                 delete [] buffer;
676         }
678         mwindow->audio_cache->check_in(edit->asset);
700 void ResourcePixmap::draw_video_resource(Edit *edit, 
701         int64_t edit_x, 
702         int64_t edit_w, 
703         int64_t pixmap_x,
704         int64_t pixmap_w,
705         int refresh_x, 
706         int refresh_w)
708 // pixels spanned by a picon
709         int64_t picon_w = Units::round(edit->picon_w());
710         int64_t picon_h = edit->picon_h();
713 // Don't draw video if picon is bigger than edit
714         if(picon_w > edit_w) return;
716 // pixels spanned by a frame
717         double frame_w = edit->frame_w();
719 // Frames spanned by a picon
720         double frames_per_picon = edit->frames_per_picon();
722 // Current pixel relative to pixmap
723         int x = 0;
724         int y = 0;
725         if(mwindow->edl->session->show_titles) 
726                 y += mwindow->theme->get_image("title_bg_data")->get_h();
727 // Frame in project touched by current pixel
728         int64_t project_frame;
730 // Get first frame touched by x and fix x to start of frame
731         if(frames_per_picon > 1)
732         {
733                 int picon = Units::to_int64(
734                         (double)(refresh_x + pixmap_x - edit_x) / 
735                         picon_w);
736                 x = picon_w * picon + edit_x - pixmap_x;
737                 project_frame = Units::to_int64((double)picon * frames_per_picon);
738         }
739         else
740         {
741                 project_frame = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) / 
742                         frame_w);
743                 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
744         }
746         File *source = mwindow->video_cache->check_out(edit->asset, mwindow->edl);
747         if(!source) return;
749         while(x < refresh_x + refresh_w)
750         {
751                 int64_t source_frame = project_frame + edit->startsource;
752                 source->set_layer(edit->channel);
753                 source->set_video_position(source_frame, 
754                         mwindow->edl->session->frame_rate);
756 // Try displaying from source cache
757                 FrameCache *frame_cache = source->get_frame_cache();
758                 VFrame *picon_frame = 0;
759                 int use_cache = 0;
761                 if((picon_frame = frame_cache->get_frame_ptr(source_frame,
762                         mwindow->edl->session->frame_rate,
763                         BC_RGB888,
764                         picon_w,
765                         picon_h)) != 0)
766                 {
767                         use_cache = 1;
768                 }
769                 else
770 // Display from file and put in cache
771                 {
772                         if(canvas->temp_picon &&
773                                 (canvas->temp_picon->get_w() != edit->asset->width ||
774                                 canvas->temp_picon->get_h() != edit->asset->height))
775                         {
776                                 delete canvas->temp_picon;
777                                 canvas->temp_picon = 0;
778                         }
780                         if(!canvas->temp_picon)
781                         {
782                                 canvas->temp_picon = new VFrame(0, 
783                                         edit->asset->width, 
784                                         edit->asset->height, 
785                                         BC_RGB888);
786                         }
788                         source->read_frame(canvas->temp_picon);
789                         picon_frame = new VFrame(0, picon_w, picon_h, BC_RGB888);
790                         frame_cache->put_frame(picon_frame, 
791                                 source_frame,
792                                 mwindow->edl->session->frame_rate,
793                                 0);
794                         cmodel_transfer(picon_frame->get_rows(),
795                                 canvas->temp_picon->get_rows(),
796                                 0,
797                                 0,
798                                 0,
799                                 0,
800                                 0,
801                                 0,
802                                 0,
803                                 0, 
804                                 canvas->temp_picon->get_w(),
805                                 canvas->temp_picon->get_h(),
806                                 0,
807                                 0,
808                                 picon_frame->get_w(), 
809                                 picon_frame->get_h(),
810                                 BC_RGB888,
811                                 BC_RGB888,
812                                 0,
813                                 canvas->temp_picon->get_bytes_per_line(),
814                                 picon_frame->get_bytes_per_line());
815                 }
817                 draw_vframe(picon_frame, 
818                         x, 
819                         y, 
820                         picon_w, 
821                         picon_h, 
822                         0, 
823                         0);
826                 if(use_cache)
827                         frame_cache->unlock();
828                 
829                 if(frames_per_picon > 1)
830                 {
831                         x += Units::round(picon_w);
832                         project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
833                 }
834                 else
835                 {
836                         x += Units::round(frame_w);
837                         project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
838                 }
841                 canvas->test_timer();
842         }
844         if(source)
845         {
846                 mwindow->video_cache->check_in(edit->asset);
847         }
851 void ResourcePixmap::dump()
853         printf("ResourcePixmap %p\n", this);
854         printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);