no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / exportedl.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2006 Andraz Tori
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 #include "asset.h"
23 #include "bchash.h"
24 #include "condition.h"
25 #include "confirmsave.h"
26 #include "edits.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "file.h"
30 #include "filesystem.h"
31 #include "filexml.h"
32 #include "language.h"
33 #include "localsession.h"
34 #include "mainerror.h"
35 #include "mainsession.h"
36 #include "mutex.h"
37 #include "mwindowgui.h"
38 #include "mwindow.h"
39 #include "exportedl.h"
40 #include "tracks.h"
41 #include "transition.h"
42 #if defined (__FreeBSD__) || defined (__NetBSD__)
43 #include <libgen.h>
44 #endif
45 #include <ctype.h>
46 #include <string.h>
47
48 ExportEDLAsset::ExportEDLAsset(MWindow *mwindow, EDL *edl)
49 {
50         this->mwindow = mwindow;
51         this->edl = edl;
52
53         path[0] = 0;
54         edl_type = EDLTYPE_CMX3600;
55         track_number = -1;
56 }
57
58 ExportEDLAsset::~ExportEDLAsset()
59 {
60 }
61
62 void ExportEDLAsset::double_to_CMX3600(double seconds, double frame_rate, char *str)
63 {
64         char tmp[20];
65         Units::totext(tmp,
66                         seconds,
67                         TIME_HMSF,
68                         0, // sample_rate ... unnecessary
69                         frame_rate,
70                         0); // frames per foot
71         if ((int)(seconds / 3600) <= 9)
72         {
73                 str[0]='0';
74                 strcpy(str+1, tmp);
75         } else
76         {
77                 strcpy(str, tmp);
78         }
79
80 //      str[8]='.';
81
82         //sprintf(str, "%02d:%02d:%02d:%02d", hour, minute, second, hundredths);
83 }
84
85 int ExportEDLAsset::edit_to_timecodes(Edit *edit,
86         char *sourceinpoint, char *sourceoutpoint,
87         char *destinpoint, char *destoutpoint,
88         char *reel_name)
89 {
90         Track *track = edit->track;
91         double frame_rate = edit->track->edl->session->frame_rate;
92
93         double edit_sourcestart;
94         double edit_sourceend;
95         double edit_deststart;
96         double edit_destend;
97         double timecode_offset;
98         
99         // timecode_offset in seconds
100         timecode_offset = edit->track->edl->session->timecode_offset;
101         //printf("tc offset %f, \n", timecode_offset);
102         
103         
104         if(!strcmp(reel_name,""))
105         strcpy(reel_name, "   BL   ");
106         edit_sourcestart = track->from_units(edit->startsource);
107         edit_sourceend = track->from_units(edit->length + edit->startsource);
108         
109         edit_deststart = track->from_units(edit->startproject);
110         edit_destend = track->from_units(edit->startproject + edit->length);
111
112         double_to_CMX3600(edit_sourcestart, frame_rate, sourceinpoint);
113         double_to_CMX3600(edit_sourceend, frame_rate, sourceoutpoint);
114         double_to_CMX3600(edit_deststart + timecode_offset, frame_rate, destinpoint);
115         double_to_CMX3600(edit_destend + timecode_offset, frame_rate, destoutpoint);
116
117         return 0;
118 }
119
120
121 void ExportEDLAsset::export_it()
122 {
123         FILE *fh;
124         fh = fopen(path, "w+");
125         if( !fh ) {
126                 eprintf("unable to open file: %s", path);
127                 return;
128         }
129
130 // We currently only support exporting one track at a time
131 // Find the track...
132         int serial = 0;
133         Track *track;
134         for(track = edl->tracks->first;
135                 track;
136                 track = track->next)
137         {
138                 if (serial == track_number)
139                         break;
140                 serial ++;
141         }
142
143
144         int last_dissolve = 1;
145
146         if (edl_type == EDLTYPE_CMX3600)
147         {
148
149                 // TODO: Find docs about exact header for CMX3600
150                 // https://xmil.biz/EDL-X/CMX3600.pdf
151                 double frame_rate = edl->session->frame_rate;
152                 int frame_rate_int = (int)frame_rate;
153                 char proj_title[BCTEXTLEN];
154                 strcpy(proj_title,basename(mwindow->session->filename));
155                 fprintf(fh, "TITLE: %s fps: %f\n", proj_title, frame_rate);
156                 switch(frame_rate_int) {
157                 case 24:
158                 case 25:
159                 case 50:
160                 case 60:
161                 case 30:
162                 {
163                 if (frame_rate - frame_rate_int < 0.001)
164                 fprintf(fh, "FCM: NON-DROP FRAME\n"); // fixme: select depending on fps
165                 break;
166                 }
167                 default:
168                 {
169                 if ((frame_rate - frame_rate_int) > 0.001)
170                 fprintf(fh, "FCM: DROP FRAME\n");
171                 }
172                 }
173                 // newline after FCM
174                 fprintf(fh, "\n");
175                 
176                 int colnum = 1;
177
178
179                 for (Edit *edit = track->edits->first;
180                         edit;
181                         edit = edit->next)
182                 {
183                 
184                 // max number of entries in cmx3600
185                 if (colnum > 999)
186                 return;
187                 
188                         char reel_name[BCTEXTLEN];
189                         char avselect[5];
190                         char edittype[5] = "C   ";
191                         char cutinfo[4] = "   ";
192                         char sourceinpoint[12];
193                         char sourceoutpoint[12];
194                         char destinpoint[12];
195                         char destoutpoint[12];
196                         
197                         char filename[1024];
198                         if (edit->asset)
199                         strcpy(filename,basename(edit->asset->path));
200                         
201                         if(!edit->asset)
202                         strcpy(reel_name,"BL  ");
203                         else
204                         strcpy(reel_name,"AX  ");
205                         
206                         if (track->data_type == TRACK_AUDIO)
207                                 strcpy(avselect, "A   ");
208                         else
209                                 strcpy(avselect, "V   ");
210
211                         //if (edit->transition)
212                         //      printf("title: %s, length: %i\n", edit->transition->title, edit->transition->length);
213                         if (edit->transition && !strcmp(edit->transition->title, "Dissolve"))
214                         {
215                                 char last_sourceout[12];
216                                 edit_to_timecodes(edit->previous, sourceinpoint, last_sourceout, destinpoint, destoutpoint, reel_name);
217                                 edit_to_timecodes(edit, sourceinpoint, sourceoutpoint, destinpoint, destoutpoint, reel_name);
218
219                                 if (last_dissolve)
220                                 {
221                                         fprintf(fh, "%03d %8s %s %4s %3s", colnum, reel_name, avselect, edittype, cutinfo);
222                                         fprintf(fh, " %s %s", last_sourceout, last_sourceout);
223                                         fprintf(fh, " %s %s", destinpoint, destinpoint);
224                                         fprintf(fh,"\n");
225                                         if(edit->asset)
226                                         fprintf(fh,"* FROM CLIP NAME: %s\n", filename);
227                                 } else
228                                 {
229                                         colnum --;
230                                 }
231                                 edittype[0] = 'D';
232                                 fprintf(fh, "%03d %8s %s %4s %03jd", colnum, reel_name, avselect, edittype, edit->transition->length);
233                                 fprintf(fh, " %s %s", sourceinpoint, sourceoutpoint);
234                                 fprintf(fh, " %s %s", destinpoint, destoutpoint);
235                                 fprintf(fh,"\n");
236                                 if(edit->asset)
237                                 fprintf(fh,"* FROM CLIP NAME: %s\n", filename);
238                                 last_dissolve = 1;
239                         } else
240                         {
241                                 edit_to_timecodes(edit, sourceinpoint, sourceoutpoint, destinpoint, destoutpoint, reel_name);
242                                 fprintf(fh, "%03d %8s %s %4s %3s", colnum, reel_name, avselect, edittype, cutinfo);
243                                 fprintf(fh, " %s %s", sourceinpoint, sourceoutpoint);
244                                 fprintf(fh, " %s %s", destinpoint, destoutpoint);
245                                 fprintf(fh,"\n");
246                                 if(edit->asset)
247                                 fprintf(fh,"* FROM CLIP NAME: %s\n", filename);
248                                 last_dissolve = 0;
249                         }
250
251                         colnum ++;
252
253                 }
254                 
255                 fprintf(fh, "\n");
256                 
257                 // file end for final cut pro 1.2.5 ?
258                 fprintf(fh, "\x0D");
259                 fprintf(fh, "\x0A");
260                 fprintf(fh, "\x1A");
261                 fprintf(fh, "\x1A");
262
263         }
264
265         fclose(fh);
266
267
268 }
269
270
271
272 int ExportEDLAsset::load_defaults()
273 {
274         mwindow->defaults->get("EDLEXPORT_PATH", path);
275         mwindow->defaults->get("EDLEXPORT_TYPE", edl_type);
276         mwindow->defaults->get("EDLEXPORT_TRACKNUMBER", track_number);
277         //load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOADMODE_NEW_TRACKS);
278
279
280         return 0;
281 }
282
283 int ExportEDLAsset::save_defaults()
284 {
285         mwindow->defaults->update("EDLEXPORT_PATH", path);
286         mwindow->defaults->update("EDLEXPORT_TYPE", edl_type);
287         mwindow->defaults->update("EDLEXPORT_TRACKNUMBER", track_number);
288         return 0;
289 }
290
291
292
293
294 ExportEDLItem::ExportEDLItem(MWindow *mwindow)
295  : BC_MenuItem(_("Export EDL..."), "Shift-E", 'E')
296 {
297         this->mwindow = mwindow;
298         set_shift(1);
299 }
300
301 int ExportEDLItem::handle_event()
302 {
303         mwindow->exportedl->start_interactive();
304         return 1;
305 }
306
307
308
309
310
311 ExportEDL::ExportEDL(MWindow *mwindow)
312  : Thread(0, 0, 0)
313 {
314         this->mwindow = mwindow;
315 //      package_lock = new Mutex("ExportEDL::package_lock");
316 //      counter_lock = new Mutex("ExportEDL::counter_lock");
317 //      completion = new Condition(0, "ExportEDL::completion");
318 //      progress_timer = new Timer;
319 }
320
321 ExportEDL::~ExportEDL()
322 {
323 //      delete package_lock;
324 //      delete counter_lock;
325 //      delete completion;
326 ///     if(preferences) delete preferences;
327 //      delete progress_timer;
328 }
329
330 void ExportEDL::start_interactive()
331 {
332         if(!Thread::running())
333         {
334                 Thread::start();
335         }
336 }
337
338 void ExportEDL::run()
339 {
340         int result = 0;
341         exportasset = new ExportEDLAsset(mwindow, mwindow->edl);
342
343         exportasset->load_defaults();
344
345 // Get format from user
346                 result = 0;
347                 int filesok;
348
349                 do {
350                 // FIX
351                         filesok = 0;
352                         exportedl_window = new ExportEDLWindow(mwindow, this, exportasset);
353                         exportedl_window->create_objects();
354                         result = exportedl_window->run_window();
355                         if (! result) {
356                                 // add to recentlist only on OK
357                                 // Fix "EDL"!
358                                 exportedl_window->path_recent->add_item("EDLPATH", exportasset->path);
359                         }
360                         exportasset->track_number = exportedl_window->track_list->get_selection_number(0, 0);
361
362                         delete exportedl_window;
363                         exportedl_window = 0;
364                         if (!result)
365                         {
366                                 ArrayList<char*> paths;
367
368                                 paths.append(exportasset->path);
369                                 filesok = ConfirmSave::test_files(mwindow, &paths);
370                         }
371
372                 } while (!result && filesok);
373         mwindow->save_defaults();
374         exportasset->save_defaults();
375
376 // FIX
377         if(!result) exportasset->export_it();
378
379
380         delete exportasset;
381
382 }
383
384 #define WIDTH xS(410)
385 #define HEIGHT yS(400)
386
387 static const char *default_list_titles[] = {
388         N_("No."),
389         N_("Track name")
390 };
391
392 static int default_list_widths[] = {
393         40,
394         200
395 };
396
397
398 ExportEDLWindow::ExportEDLWindow(MWindow *mwindow, ExportEDL *exportedl, ExportEDLAsset *exportasset)
399  : BC_Window(_(PROGRAM_NAME ": Export EDL"),
400         mwindow->gui->get_screen_w(1, 0) / 2 - WIDTH / 2,
401         mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
402         WIDTH, HEIGHT, (int)BC_INFINITY, (int)BC_INFINITY, 0, 0, 1)
403 {
404         this->mwindow = mwindow;
405         this->exportasset = exportasset;
406 // *** CONTEXT_HELP ***
407         context_help_set_keyword("Export to EDL");
408         for( int i=0; i<2; ++i ) {
409                 list_titles[i] = _(default_list_titles[i]);
410                 list_widths[i] = xS(default_list_widths[i]);
411         }
412 }
413
414 ExportEDLWindow::~ExportEDLWindow()
415 {
416 //      delete format_tools;
417 //      delete loadmode;
418 }
419
420
421 void ExportEDLWindow::create_objects()
422 {
423         int xs5 = xS(5);
424         int ys5 = yS(5), ys25 = yS(25);
425         lock_window("ExportEDLWindow::create_objects");
426         int x = xs5, y = ys5;
427         add_subwindow(new BC_Title(x, y,
428                         _("Select a file to export to:")));
429         y += ys25;
430
431         add_subwindow(path_textbox = new ExportEDLPathText(x, y, this));
432         x += xS(300);
433         path_recent = new BC_RecentList("EDLPATH", mwindow->defaults,
434                                         path_textbox, 10, x, y, xS(300), yS(100));
435         add_subwindow(path_recent);
436 // FIX
437         path_recent->load_items("EDLPATH");
438
439         x += xS(24);
440         add_subwindow(path_button = new BrowseButton(
441                 mwindow->theme, this, path_textbox, x, y - 4, exportasset->path,
442                 _("Output to file"), _("Select a file to write to:"), 0));
443
444         y += xS(34);
445         x = xs5;
446         add_subwindow(new BC_Title(x, y, _("Select track to be exported:")));
447         y += ys25;
448
449
450         items_tracks[0].remove_all_objects();
451         items_tracks[1].remove_all_objects();
452         int serial = 0;
453         if (exportasset->track_number == -1)
454                 exportasset->track_number = 0;
455         for(Track *track = mwindow->edl->tracks->first;
456                 track;
457                 track = track->next)
458         {
459
460                 char tmp[16];
461                 sprintf(tmp, "%i\n", serial+1);
462
463                 BC_ListBoxItem *listitem = new BC_ListBoxItem(tmp);
464                 if (serial == exportasset->track_number)
465                         listitem->set_selected(1);
466                 items_tracks[0].append(listitem);
467                 items_tracks[1].append(new BC_ListBoxItem(track->title));
468                 serial ++;
469
470         }
471
472
473         add_subwindow(track_list = new ExportEDLWindowTrackList(this, x, y, xS(400), yS(200)));
474
475         y += 5 + track_list->get_h();
476         add_subwindow(new BC_Title(x, y, _("Currently only CMX 3600 format is supported")));
477
478
479         add_subwindow(new BC_OKButton(this));
480         add_subwindow(new BC_CancelButton(this));
481         show_window();
482         unlock_window();
483 }
484
485
486 ExportEDLPathText::ExportEDLPathText(int x, int y, ExportEDLWindow *window)
487  : BC_TextBox(x, y, xS(300), 1, window->exportasset->path)
488 {
489         this->window = window;
490 }
491 ExportEDLPathText::~ExportEDLPathText()
492 {
493 }
494 int ExportEDLPathText::handle_event()
495 {
496         strcpy(window->exportasset->path, get_text());
497 //      window->handle_event();
498         return 1;
499 }
500
501 ExportEDLWindowTrackList::ExportEDLWindowTrackList(ExportEDLWindow *window,
502         int x, int y, int w, int h)
503  : BC_ListBox(x, y, w, h, LISTBOX_TEXT,
504                 window->items_tracks,
505                 window->list_titles,
506                 window->list_widths,
507                 2)
508 {
509         this->window = window;
510 }
511
512 int ExportEDLWindowTrackList::handle_event()
513 {
514 //      window->exportasset->track_number = get_selection_number(0, 0);
515 //      printf("aaaaa %i\n", window->exportasset->track_number );
516 //      window->set_done(0);
517         return 1;
518 }
519