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