no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / transitionpopup.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "bcdisplayinfo.h"
24 #include "clip.h"
25 #include "edit.h"
26 #include "edl.h"
27 #include "edlsession.h"
28 #include "language.h"
29 #include "mwindow.h"
30 #include "mwindowgui.h"
31 #include "plugin.h"
32 #include "transition.h"
33 #include "track.h"
34 #include "tracks.h"
35 #include "transitionpopup.h"
36
37
38 TransitionLengthThread::TransitionLengthThread(MWindow *mwindow)
39  : BC_DialogThread()
40 {
41         this->mwindow = mwindow;
42 }
43
44 TransitionLengthThread::~TransitionLengthThread()
45 {
46         close_window();
47 }
48
49 void TransitionLengthThread::start(Transition *transition, double length)
50 {
51         this->transition = transition;
52         this->orig_length = length;
53         this->new_length = length;
54         BC_DialogThread::start();
55 }
56
57 #define TLW_W xS(300)
58 #define TLW_H yS(100)
59
60 BC_Window* TransitionLengthThread::new_gui()
61 {
62         BC_DisplayInfo display_info;
63         int x = display_info.get_abs_cursor_x() - TLW_W / 2;
64         int y = display_info.get_abs_cursor_y() - TLW_H / 2;
65         TransitionLengthDialog *gui = new TransitionLengthDialog(mwindow, this, x, y);
66         gui->create_objects();
67         return gui;
68 }
69
70 void TransitionLengthThread::handle_close_event(int result)
71 {
72         if( mwindow->in_destructor ) return;
73         if( !result ) {
74                 if( transition )
75                         mwindow->set_transition_length(transition, new_length);
76                 else
77                         mwindow->set_transition_length(new_length);
78         }
79         else
80                 update(orig_length);
81 }
82
83 int TransitionLengthThread::update(double length)
84 {
85         if( !EQUIV(this->new_length, length) ) {
86                 this->new_length = length;
87                 if( transition ) {
88                         transition->length = transition->track->to_units(length, 1);
89                         mwindow->sync_parameters(CHANGE_EDL);
90                         mwindow->gui->lock_window();
91                         mwindow->gui->draw_overlays(1);
92                         mwindow->gui->unlock_window();
93                 }
94         }
95         return 1;
96 }
97
98
99 TransitionUnitsItem::TransitionUnitsItem(TransitionUnitsPopup *popup,
100                 const char *text, int id)
101  : BC_MenuItem(text)
102 {
103         this->popup = popup;
104         this->id = id;
105 }
106
107 TransitionUnitsItem::~TransitionUnitsItem()
108 {
109 }
110
111 int TransitionUnitsItem::handle_event()
112 {
113         TransitionUnitsPopup *units_popup = (TransitionUnitsPopup *)get_popup_menu();
114         TransitionLengthDialog *gui = units_popup->gui;
115         double length = gui->thread->new_length;
116         units_popup->units = id;
117         gui->update_text(length);
118         units_popup->set_text(get_text());
119         return 1;
120 }
121
122 TransitionUnitsPopup::TransitionUnitsPopup(TransitionLengthDialog *gui, int x, int y)
123  : BC_PopupMenu(x, y, xS(120), "", 1)
124 {
125         this->gui = gui;
126         units = TIME_SECONDS;
127 }
128
129 TransitionUnitsPopup::~TransitionUnitsPopup()
130 {
131 }
132
133 void TransitionUnitsPopup::create_objects()
134 {
135         TransitionUnitsItem *units_item;
136         add_item(units_item = new TransitionUnitsItem(this, _("Seconds"), TIME_SECONDS));
137         add_item(new TransitionUnitsItem(this, _("Frames"), TIME_FRAMES));
138         add_item(new TransitionUnitsItem(this, _("Samples"), TIME_SAMPLES));
139         add_item(new TransitionUnitsItem(this, _("H:M:S.xxx"), TIME_HMS));
140         add_item(new TransitionUnitsItem(this, _("H:M:S:frm"), TIME_HMSF));
141         set_text(units_item->get_text());
142 }
143
144
145 TransitionLengthDialog::TransitionLengthDialog(MWindow *mwindow,
146         TransitionLengthThread *thread, int x, int y)
147  : BC_Window(_(PROGRAM_NAME ": Transition length"), x, y,
148                 TLW_W, TLW_H, -1, -1, 0, 0, 1)
149 {
150         this->mwindow = mwindow;
151         this->thread = thread;
152 // *** CONTEXT_HELP ***
153         context_help_set_keyword("Transition Plugins");
154 }
155
156 TransitionLengthDialog::~TransitionLengthDialog()
157 {
158 }
159
160
161 void TransitionLengthDialog::create_objects()
162 {
163         lock_window("TransitionLengthDialog::create_objects");
164         add_subwindow(units_popup = new TransitionUnitsPopup(this, xS(10), yS(10)));
165         units_popup->create_objects();
166         text = new TransitionLengthText(mwindow, this, xS(160), yS(10));
167         text->create_objects();
168         text->set_precision(3);
169         text->set_increment(0.1);
170         add_subwindow(new BC_OKButton(this));
171         add_subwindow(new BC_CancelButton(this));
172         show_window();
173         unlock_window();
174 }
175
176 int TransitionLengthDialog::close_event()
177 {
178         set_done(0);
179         return 1;
180 }
181
182 void TransitionLengthDialog::update_text(double length)
183 {
184         int units = units_popup->units;
185         EDLSession *session = mwindow->edl->session;
186         char string[BCSTRLEN];
187         Units::totext(string, length, units,
188                 session->sample_rate, session->frame_rate,
189                 session->frames_per_foot);
190         text->update(string);
191 }
192
193
194 TransitionLengthText::TransitionLengthText(MWindow *mwindow,
195         TransitionLengthDialog *gui, int x, int y)
196  : BC_TumbleTextBox(gui, (float)gui->thread->new_length,
197                 0.f, 100.f, x, y, xS(100))
198 {
199         this->mwindow = mwindow;
200         this->gui = gui;
201 }
202
203 int TransitionLengthText::handle_event()
204 {
205         const char *text = get_text();
206         int units = gui->units_popup->units;
207         EDLSession *session = gui->mwindow->edl->session;
208         double result = Units::text_to_seconds(text, session->sample_rate,
209                 units, session->frame_rate, session->frames_per_foot);
210         return gui->thread->update(result);
211 }
212
213 int TransitionLengthText::handle_up_down(int dir)
214 {
215         double delta = 0;
216         int units = gui->units_popup->units;
217         EDLSession *session = gui->mwindow->edl->session;
218         switch( units ) {
219         case TIME_SECONDS:
220         case TIME_HMS:
221                 delta = 0.1;
222                 break;
223         case TIME_HMSF:
224         case TIME_FRAMES:
225                 delta = session->frame_rate > 0 ? 1./session->frame_rate : 0;
226                 break;
227         case TIME_SAMPLES:
228                 delta = session->sample_rate > 0 ? 1./session->sample_rate : 0;
229                 break;
230         }
231         double length = gui->thread->new_length + delta * dir;
232         gui->update_text(length);
233         return gui->thread->update(length);
234 }
235
236 int TransitionLengthText::handle_up_event()
237 {
238         return handle_up_down(+1);
239 }
240 int TransitionLengthText::handle_down_event()
241 {
242         return handle_up_down(-1);
243 }
244
245
246 TransitionPopup::TransitionPopup(MWindow *mwindow, MWindowGUI *gui)
247  : BC_PopupMenu(0, 0, 0, "", 0)
248 {
249         this->mwindow = mwindow;
250         this->gui = gui;
251 }
252
253 TransitionPopup::~TransitionPopup()
254 {
255         delete length_thread;
256 //      delete dialog_thread;
257 }
258
259
260 void TransitionPopup::create_objects()
261 {
262         length_thread = new TransitionLengthThread(mwindow);
263 //      add_item(attach = new TransitionPopupAttach(mwindow, this));
264         add_item(show = new TransitionPopupShow(mwindow, this));
265         add_item(on = new TransitionPopupOn(mwindow, this));
266         add_item(length_item = new TransitionPopupLength(mwindow, this));
267         add_item(detach = new TransitionPopupDetach(mwindow, this));
268 }
269
270 int TransitionPopup::update(Transition *transition)
271 {
272         this->transition = transition;
273         show->set_checked(transition->show);
274         on->set_checked(transition->on);
275         char len_text[50];
276         sprintf(len_text, _("Length: %2.2f sec"), transition->track->from_units(transition->length));
277         length_item->set_text(len_text);
278         return 0;
279 }
280
281
282 TransitionPopupAttach::TransitionPopupAttach(MWindow *mwindow, TransitionPopup *popup)
283  : BC_MenuItem(_("Attach..."))
284 {
285         this->mwindow = mwindow;
286         this->popup = popup;
287 }
288
289 TransitionPopupAttach::~TransitionPopupAttach()
290 {
291 }
292
293 int TransitionPopupAttach::handle_event()
294 {
295 //      popup->dialog_thread->start();
296         return 1;
297 }
298
299
300 TransitionPopupDetach::TransitionPopupDetach(MWindow *mwindow, TransitionPopup *popup)
301  : BC_MenuItem(_("Detach"))
302 {
303         this->mwindow = mwindow;
304         this->popup = popup;
305 }
306
307 TransitionPopupDetach::~TransitionPopupDetach()
308 {
309 }
310
311 int TransitionPopupDetach::handle_event()
312 {
313         mwindow->detach_transition(popup->transition);
314         return 1;
315 }
316
317
318 TransitionPopupOn::TransitionPopupOn(MWindow *mwindow, TransitionPopup *popup)
319  : BC_MenuItem(_("On"))
320 {
321         this->mwindow = mwindow;
322         this->popup = popup;
323 }
324
325 TransitionPopupOn::~TransitionPopupOn()
326 {
327 }
328
329 int TransitionPopupOn::handle_event()
330 {
331         popup->transition->on = !get_checked();
332         mwindow->sync_parameters(CHANGE_EDL);
333         return 1;
334 }
335
336
337 TransitionPopupShow::TransitionPopupShow(MWindow *mwindow, TransitionPopup *popup)
338  : BC_MenuItem(_("Show"))
339 {
340         this->mwindow = mwindow;
341         this->popup = popup;
342 }
343
344 TransitionPopupShow::~TransitionPopupShow()
345 {
346 }
347
348 int TransitionPopupShow::handle_event()
349 {
350         mwindow->show_plugin(popup->transition);
351         return 1;
352 }
353
354
355 TransitionPopupLength::TransitionPopupLength(MWindow *mwindow, TransitionPopup *popup)
356  : BC_MenuItem(_("Length"))
357 {
358         this->mwindow = mwindow;
359         this->popup = popup;
360 }
361
362 TransitionPopupLength::~TransitionPopupLength()
363 {
364 }
365
366 int TransitionPopupLength::handle_event()
367 {
368         Transition *transition = popup->transition;
369         double length = transition->edit->track->from_units(transition->length);
370         popup->length_thread->start(popup->transition, length);
371         return 1;
372 }
373