6 #include "edlsession.h"
8 #include "filesystem.h"
11 #include "indexfile.h"
12 #include "indexthread.h"
14 #include "localsession.h"
15 #include "mainprogress.h"
17 #include "mwindowgui.h"
18 #include "preferences.h"
19 #include "resourcepixmap.h"
22 #include "trackcanvas.h"
26 // Use native sampling rates for files so the same index can be used in
29 IndexFile::IndexFile(MWindow *mwindow)
31 //printf("IndexFile::IndexFile 1\n");
32 this->mwindow = mwindow;
33 //printf("IndexFile::IndexFile 2\n");
36 redraw_timer = new Timer;
39 IndexFile::IndexFile(MWindow *mwindow, Asset *asset)
41 //printf("IndexFile::IndexFile 2\n");
43 this->mwindow = mwindow;
46 redraw_timer = new Timer;
49 IndexFile::~IndexFile()
51 //printf("IndexFile::~IndexFile 1\n");
55 int IndexFile::open_index(Asset *asset)
57 // use buffer if being built
61 //printf("IndexFile::open_index 1\n");
62 if(asset->index_status == INDEX_BUILDING)
68 if(!(result = open_file()))
70 // opened existing file
73 //printf("IndexFile::open_index 2\n");
79 //printf("IndexFile::open_index 3\n");
80 asset->index_status = INDEX_READY;
87 //printf("IndexFile::open_index 4 %d\n", result);
92 int IndexFile::open_index(MWindow *mwindow, Asset *asset)
94 return open_index(asset);
97 void IndexFile::delete_index(Preferences *preferences, Asset *asset)
99 char index_filename[BCTEXTLEN];
100 char source_filename[BCTEXTLEN];
101 get_index_filename(source_filename,
102 preferences->index_directory,
105 //printf("IndexFile::delete_index %s %s\n", source_filename, index_filename);
106 remove(index_filename);
109 int IndexFile::open_file()
112 get_index_filename(source_filename,
113 mwindow->preferences->index_directory,
117 //printf("IndexFile::open_file 1 %s\n", index_filename);
118 if(file = fopen(index_filename, "rb"))
120 // Index file already exists.
121 // Get its last size without changing the status.
124 read_info(&test_asset);
127 //printf("IndexFile::open_file 1.5 %s %u %u\n",
129 //fs.get_date(index_filename),
130 //fs.get_date(test_asset.path));
131 if(fs.get_date(index_filename) < fs.get_date(test_asset.path))
133 // index older than source
134 //printf("IndexFile::open_file 2\n", index_filename);
139 if(fs.get_size(asset->path) != test_asset.index_bytes)
141 // source file is a different size than index source file
142 //printf("IndexFile::open_file 3 %s %lld %lld %lld\n",
144 //fs.get_size(asset->path),
145 //test_asset.index_bytes,
146 //asset->index_bytes);
152 //printf("IndexFile::open_file 4 %s %lld %lld %lld\n",
154 //fs.get_size(asset->path),
155 //test_asset.index_bytes,
156 //asset->index_bytes);
157 fseek(file, 0, SEEK_END);
158 file_length = ftell(file);
159 fseek(file, 0, SEEK_SET);
166 //printf("IndexFile::open_file 5\n", index_filename);
173 int IndexFile::open_source(File *source)
175 //printf("IndexFile::open_source %p %s\n", asset, asset->path);
176 if(source->open_file(mwindow->plugindb,
183 //printf("IndexFile::open_source() Couldn't open %s.\n", asset->path);
189 asset->index_bytes = fs.get_size(asset->path);
194 int64_t IndexFile::get_required_scale(File *source)
197 // total length of input file
198 int64_t length_source = source->get_audio_length(0);
200 // get scale of index file
201 // if(length_source > mwindow->preferences->index_size)
203 // Total peaks which may be stored in buffer
204 int64_t peak_count = mwindow->preferences->index_size / (2 * sizeof(float) * asset->channels);
206 length_source / result > peak_count;
212 // too small to build an index for
216 // Takes too long to draw from source on a CDROM. Make indexes for
222 int IndexFile::get_index_filename(char *source_filename,
223 char *index_directory,
224 char *index_filename,
225 char *input_filename)
227 // Replace slashes and dots
229 int len = strlen(input_filename);
230 for(i = 0, j = 0; i < len; i++)
232 if(input_filename[i] != '/' &&
233 input_filename[i] != '.')
234 source_filename[j++] = input_filename[i];
238 source_filename[j++] = '_';
241 source_filename[j] = 0;
243 fs.join_names(index_filename, index_directory, source_filename);
244 strcat(index_filename, ".idx");
248 int IndexFile::interrupt_index()
254 // Read data into buffers
256 int IndexFile::create_index(Asset *asset, MainProgressBar *progress)
259 IndexThread *index_thread;
260 this->mwindow = mwindow;
264 // open the source file
266 if(open_source(&source)) return 1;
268 asset->index_zoom = get_required_scale(&source);
270 // Indexes are now built for everything since it takes too long to draw
271 // from CDROM source.
274 // total length of input file
275 int64_t length_source = source.get_audio_length(0);
277 // get amount to read at a time in floats
278 int64_t buffersize = 65536;
280 get_index_filename(source_filename,
281 mwindow->preferences->index_directory,
284 sprintf(string, _("Creating %s."), index_filename);
286 progress->update_title(string);
287 progress->update_length(length_source);
288 redraw_timer->update();
290 // thread out index thread
291 index_thread = new IndexThread(mwindow,
297 index_thread->start_build();
299 // current sample in source file
300 int64_t position = 0;
301 int64_t fragment_size = buffersize;
302 int current_buffer = 0;
305 // pass through file once
306 while(position < length_source && !result)
308 if(length_source - position < fragment_size && fragment_size == buffersize) fragment_size = length_source - position;
310 index_thread->input_lock[current_buffer]->lock("IndexFile::create_index 1");
311 index_thread->input_len[current_buffer] = fragment_size;
313 int cancelled = progress->update(position);
315 index_thread->interrupt_flag ||
321 for(int channel = 0; !result && channel < asset->channels; channel++)
323 source.set_audio_position(position, 0);
324 source.set_channel(channel);
326 // Read from source file
327 if(source.read_samples(index_thread->buffer_in[current_buffer][channel],
332 // Release buffer to thread
335 index_thread->output_lock[current_buffer]->unlock();
337 if(current_buffer >= TOTAL_BUFFERS) current_buffer = 0;
338 position += fragment_size;
342 index_thread->input_lock[current_buffer]->unlock();
346 // end thread cleanly
347 index_thread->input_lock[current_buffer]->lock("IndexFile::create_index 2");
348 index_thread->last_buffer[current_buffer] = 1;
349 index_thread->output_lock[current_buffer]->unlock();
351 index_thread->stop_build();
359 mwindow->edl->set_index_file(asset);
360 //printf("IndexFile::create_index 11\n");
365 int IndexFile::create_index(MWindow *mwindow,
367 MainProgressBar *progress)
369 return create_index(asset, progress);
374 int IndexFile::redraw_edits(int force)
376 int64_t difference = redraw_timer->get_scaled_difference(1000);
378 //printf("IndexFile::redraw_edits 1 %d %d\n", difference, force);
379 if(difference > 250 || force)
381 redraw_timer->update();
382 // Can't lock window here since the window is only redrawn when the pixel
384 //printf("IndexFile::redraw_edits 2\n");
385 mwindow->gui->lock_window();
386 mwindow->edl->set_index_file(asset);
387 //printf("IndexFile::redraw_edits 3\n");
388 mwindow->gui->canvas->draw_indexes(asset);
389 //printf("IndexFile::redraw_edits 4\n");
390 asset->old_index_end = asset->index_end;
391 mwindow->gui->unlock_window();
392 //printf("IndexFile::redraw_edits 5\n");
400 int IndexFile::draw_index(ResourcePixmap *pixmap, Edit *edit, int x, int w)
402 // check against index_end when being built
403 if(asset->index_zoom == 0)
405 printf(_("IndexFile::draw_index: index has 0 zoom\n"));
408 // calculate a virtual x where the edit_x should be in floating point
409 double virtual_edit_x = 1.0 * edit->track->from_units(edit->startproject) *
410 mwindow->edl->session->sample_rate /
411 mwindow->edl->local_session->zoom_sample -
412 mwindow->edl->local_session->view_start;
414 // samples in segment to draw relative to asset
415 double asset_over_session = (double)edit->asset->sample_rate /
416 mwindow->edl->session->sample_rate;
417 int64_t startsource = (int64_t)(((pixmap->pixmap_x - virtual_edit_x + x) *
418 mwindow->edl->local_session->zoom_sample +
421 // just in case we get a numerical error
422 if (startsource < 0) startsource = 0;
423 int64_t length = (int64_t)(w *
424 mwindow->edl->local_session->zoom_sample *
427 if(asset->index_status == INDEX_BUILDING)
429 if(startsource + length > asset->index_end)
430 length = asset->index_end - startsource;
433 // length of index to read in samples * 2
434 int64_t lengthindex = length / asset->index_zoom * 2;
435 // start of data in samples
436 int64_t startindex = startsource / asset->index_zoom * 2;
437 int64_t length_read; // Actual length read from file in bytes
438 int64_t startfile, lengthfile; // Start and length of fragment to read from file in bytes.
440 int buffer_shared = 0;
442 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
443 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->title_bg_data->get_h();
444 int miny = center_pixel - mwindow->edl->local_session->zoom_track / 2;
445 int maxy = center_pixel + mwindow->edl->local_session->zoom_track / 2;
447 // get zoom_sample relative to index zoomx
448 double index_frames_per_pixel = mwindow->edl->local_session->zoom_sample /
452 // test channel number
453 if(edit->channel > asset->channels) return 1;
455 // get channel offset
456 startindex += asset->get_index_offset(edit->channel);
459 if(asset->index_status == INDEX_BUILDING)
461 // index is in RAM, being built
462 buffer = &(asset->index_buffer[startindex]);
467 // index is stored in a file
468 buffer = new float[lengthindex + 1];
470 startfile = asset->index_start + startindex * sizeof(float);
471 lengthfile = lengthindex * sizeof(float);
474 if(startfile < file_length)
476 fseek(file, startfile, SEEK_SET);
478 length_read = lengthfile;
479 if(startfile + length_read > file_length)
480 length_read = file_length - startfile;
482 fread(buffer, length_read + sizeof(float), 1, file);
485 if(length_read < lengthfile)
486 for(i = length_read / sizeof(float);
487 i < lengthfile / sizeof(float);
494 pixmap->canvas->set_color(mwindow->theme->audio_color);
497 double current_frame = 0;
498 float highsample = buffer[0];
499 float lowsample = buffer[1];
500 int prev_y1 = center_pixel;
501 int prev_y2 = center_pixel;
504 for(int bufferposition = 0;
505 bufferposition < lengthindex;
508 if(current_frame >= index_frames_per_pixel)
510 int next_y1 = (int)(center_pixel - highsample * mwindow->edl->local_session->zoom_y / 2);
511 int next_y2 = (int)(center_pixel - lowsample * mwindow->edl->local_session->zoom_y / 2);
515 // A different algorithm has to be used if it's 1 sample per pixel and the
516 // index is used. Now the min and max values are equal so we join the max samples.
517 if(mwindow->edl->local_session->zoom_sample == 1)
519 pixmap->canvas->draw_line(x1 + x - 1, prev_y1, x1 + x, y1, pixmap);
523 // Extend line height if it doesn't connect to previous line
526 if(y1 > prev_y2) y1 = prev_y2 + 1;
527 if(y2 < prev_y1) y2 = prev_y1 - 1;
533 pixmap->canvas->draw_line(x1 + x, y1, x1 + x, y2, pixmap);
535 current_frame -= index_frames_per_pixel;
539 highsample = buffer[bufferposition];
540 lowsample = buffer[bufferposition + 1];
544 highsample = MAX(highsample, buffer[bufferposition]);
545 lowsample = MIN(lowsample, buffer[bufferposition + 1]);
551 y1 = (int)(center_pixel - highsample * mwindow->edl->local_session->zoom_y / 2);
552 y2 = (int)(center_pixel - lowsample * mwindow->edl->local_session->zoom_y / 2);
553 pixmap->canvas->draw_line(x1 + x, y1, x1 + x, y2, pixmap);
559 if(!buffer_shared) delete [] buffer;
563 int IndexFile::close_index()
572 int IndexFile::remove_index()
574 if(asset->index_status == INDEX_READY || asset->index_status == INDEX_NOTTESTED)
577 remove(index_filename);
581 int IndexFile::read_info(Asset *test_asset)
583 //printf("IndexFile::read_info 1 %p\n", test_asset);
584 if(!test_asset) test_asset = asset;
585 //printf("IndexFile::read_info 2 %d\n", test_asset->index_status);
586 if(test_asset->index_status == INDEX_NOTTESTED)
588 // read start of index data
589 fread((char*)&(test_asset->index_start), sizeof(int64_t), 1, file);
591 // read test_asset info from index
594 data = new char[test_asset->index_start];
595 fread(data, test_asset->index_start - sizeof(int64_t), 1, file);
596 data[test_asset->index_start - sizeof(int64_t)] = 0;
598 xml.read_from_string(data);
599 test_asset->read(mwindow->plugindb, &xml);
602 if(test_asset->format == FILE_UNKNOWN)
604 //printf("IndexFile::read_info 3\n");