drag+drop honours labels/plugins/autos, new drag icon, phantom keyframe fix
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / cwindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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 "autos.h"
23 #include "bchash.h"
24 #include "bcsignals.h"
25 #include "channelinfo.h"
26 #include "clip.h"
27 #include "cplayback.h"
28 #include "ctimebar.h"
29 #include "ctracking.h"
30 #include "cwindow.h"
31 #include "cwindowgui.h"
32 #include "cwindowtool.h"
33 #include "edl.h"
34 #include "keys.h"
35 #include "edl.h"
36 #include "edlsession.h"
37 #include "language.h"
38 #include "localsession.h"
39 #include "mainmenu.h"
40 #include "mainsession.h"
41 #include "mbuttons.h"
42 #include "mwindow.h"
43 #include "mwindowgui.h"
44 #include "playbackengine.h"
45 #include "playtransport.h"
46 #include "preferences.h"
47 #include "remotecontrol.h"
48 #include "theme.h"
49 #include "track.h"
50 #include "trackcanvas.h"
51 #include "tracks.h"
52 #include "transportque.h"
53
54 #include <unistd.h>
55
56
57
58 CWindow::CWindow(MWindow *mwindow)
59  : Thread(1, 0, 0)
60 {
61         this->mwindow = mwindow;
62 }
63
64
65 CWindow::~CWindow()
66 {
67         if(gui && running()) {
68                 gui->set_done(0);
69         }
70         join();
71         delete gui;  gui = 0;
72         delete playback_engine;
73         delete playback_cursor;
74 }
75
76 void CWindow::create_objects()
77 {
78         destination = mwindow->defaults->get("CWINDOW_DESTINATION", 0);
79
80
81         gui = new CWindowGUI(mwindow, this);
82
83         gui->create_objects();
84
85
86         playback_engine = new CPlayback(mwindow, this, gui->canvas);
87
88
89 // Start command loop
90         playback_engine->create_objects();
91
92         gui->transport->set_engine(playback_engine);
93
94         playback_cursor = new CTracking(mwindow, this);
95
96         playback_cursor->create_objects();
97
98 }
99
100
101 void CWindow::show_window()
102 {
103         gui->lock_window("CWindow::show_cwindow");
104         gui->show_window();
105         gui->raise_window();
106         gui->flush();
107         gui->unlock_window();
108
109         gui->tool_panel->show_tool();
110 }
111
112 void CWindow::hide_window()
113 {
114         gui->hide_window();
115         gui->mwindow->session->show_cwindow = 0;
116 // Unlock in case MWindow is waiting for it.
117         gui->unlock_window();
118
119         gui->tool_panel->hide_tool();
120
121         mwindow->gui->lock_window("CWindowGUI::close_event");
122         mwindow->gui->mainmenu->show_cwindow->set_checked(0);
123         mwindow->gui->unlock_window();
124         mwindow->save_defaults();
125
126         gui->lock_window("CWindow::hide_window");
127 }
128
129
130 Track* CWindow::calculate_affected_track()
131 {
132         Track* affected_track = 0;
133         for(Track *track = mwindow->edl->tracks->first;
134                 track;
135                 track = track->next)
136         {
137                 if(track->data_type == TRACK_VIDEO &&
138                         track->record)
139                 {
140                         affected_track = track;
141                         break;
142                 }
143         }
144         return affected_track;
145 }
146
147 Auto* CWindow::calculate_affected_auto(Autos *autos,
148         int create,
149         int *created,
150         int redraw)
151 {
152         Auto* affected_auto = 0;
153         if(created) *created = 0;
154
155         if(create)
156         {
157                 int total = autos->total();
158                 affected_auto = autos->get_auto_for_editing();
159
160 // Got created
161                 if(total != autos->total())
162                 {
163                         if(created) *created = 1;
164                         if(redraw)
165                         {
166 // May have to unlock CWindowGUI here.
167                                 mwindow->gui->lock_window("CWindow::calculate_affected_auto");
168                                 mwindow->gui->draw_overlays(1);
169                                 mwindow->gui->unlock_window();
170                         }
171                 }
172         }
173         else
174         {
175                 affected_auto = autos->get_prev_auto(PLAY_FORWARD, affected_auto);
176         }
177
178         return affected_auto;
179 }
180
181
182
183 void CWindow::calculate_affected_autos(FloatAuto **x_auto,
184         FloatAuto **y_auto,
185         FloatAuto **z_auto,
186         Track *track,
187         int use_camera,
188         int create_x,
189         int create_y,
190         int create_z)
191 {
192         if(x_auto) (*x_auto) = 0;
193         if(y_auto) (*y_auto) = 0;
194         if(z_auto) (*z_auto) = 0;
195
196         if(!track) return;
197
198         if(use_camera)
199         {
200                 if(x_auto) (*x_auto) = (FloatAuto*)calculate_affected_auto(
201                         track->automation->autos[AUTOMATION_CAMERA_X], create_x);
202                 if(y_auto) (*y_auto) = (FloatAuto*)calculate_affected_auto(
203                         track->automation->autos[AUTOMATION_CAMERA_Y], create_y);
204                 if(z_auto) (*z_auto) = (FloatAuto*)calculate_affected_auto(
205                         track->automation->autos[AUTOMATION_CAMERA_Z], create_z);
206         }
207         else
208         {
209                 if(x_auto) (*x_auto) = (FloatAuto*)calculate_affected_auto(
210                         track->automation->autos[AUTOMATION_PROJECTOR_X], create_x);
211                 if(y_auto) (*y_auto) = (FloatAuto*)calculate_affected_auto(
212                         track->automation->autos[AUTOMATION_PROJECTOR_Y], create_y);
213                 if(z_auto) (*z_auto) = (FloatAuto*)calculate_affected_auto(
214                         track->automation->autos[AUTOMATION_PROJECTOR_Z], create_z);
215         }
216 }
217
218 void CWindow::stop_playback(int wait)
219 {
220         playback_engine->stop_playback(wait);
221 }
222
223 void CWindow::run()
224 {
225         gui->run_window();
226 }
227
228 void CWindow::update(int dir, int overlays, int tool_window, int operation, int timebar)
229 {
230
231         if(dir)
232                 refresh_frame(CHANGE_NONE, dir);
233
234         gui->lock_window("CWindow::update 2");
235 // Create tool window
236         if(operation)
237                 gui->set_operation(mwindow->edl->session->cwindow_operation);
238
239 // Updated by video device.
240         if(overlays && !dir)
241                 gui->canvas->draw_refresh();
242
243 // Update tool parameters
244 // Never updated by someone else
245         if(tool_window || dir)
246                 gui->update_tool();
247
248         if(timebar)
249                 gui->timebar->update(1);
250
251         double zoom = !mwindow->edl->session->cwindow_scrollbars ?
252                 0 :mwindow->edl->session->cwindow_zoom;
253         gui->zoom_panel->update(zoom);
254
255         gui->canvas->update_zoom(mwindow->edl->session->cwindow_xscroll,
256                         mwindow->edl->session->cwindow_yscroll,
257                         mwindow->edl->session->cwindow_zoom);
258         gui->canvas->reposition_window(mwindow->edl,
259                         mwindow->theme->ccanvas_x,
260                         mwindow->theme->ccanvas_y,
261                         mwindow->theme->ccanvas_w,
262                         mwindow->theme->ccanvas_h);
263
264
265
266
267         gui->unlock_window();
268
269
270
271
272 }
273
274 int CWindow::update_position(double position)
275 {
276         gui->unlock_window();
277
278         playback_engine->interrupt_playback(1);
279
280         position = mwindow->edl->align_to_frame(position, 0);
281         position = MAX(0, position);
282
283         mwindow->gui->lock_window("CWindowSlider::handle_event 2");
284         mwindow->select_point(position);
285         mwindow->gui->unlock_window();
286
287         gui->lock_window("CWindow::update_position 1");
288         return 1;
289 }
290
291 void CWindow::refresh_frame(int change_type, EDL *edl, int dir)
292 {
293         mwindow->refresh_mixers(dir);
294         playback_engine->refresh_frame(change_type, edl, dir);
295 }
296
297 void CWindow::refresh_frame(int change_type, int dir)
298 {
299         refresh_frame(change_type, mwindow->edl, dir);
300 }
301
302 CWindowRemoteHandler::
303 CWindowRemoteHandler(RemoteControl *remote_control)
304  : RemoteHandler(remote_control->gui, RED)
305 {
306         last_key = -1;
307 }
308
309 CWindowRemoteHandler::
310 ~CWindowRemoteHandler()
311 {
312 }
313
314 int CWindowRemoteHandler::remote_process_key(RemoteControl *remote_control, int key)
315 {
316         MWindowGUI *mwindow_gui = remote_control->mwindow_gui;
317         EDL *edl = mwindow_gui->mwindow->edl;
318         if( !edl ) return 0;
319         PlayTransport *transport = mwindow_gui->mbuttons->transport;
320         if( !transport->get_edl() ) return 0;
321         PlaybackEngine *engine = transport->engine;
322         double position = engine->get_tracking_position();
323         double length = edl->tracks->total_length();
324         int next_command = -1, lastkey = last_key;
325         last_key = key;
326
327         switch( key ) {
328         case '1': case '2': case '3': case '4':
329         case '5': case '6': case '7': case '8':
330                 if( lastkey == 'e' ) {
331                         mwindow_gui->mwindow->select_asset(key-'1', 1);
332                         break;
333                 } // fall through
334         case '0': case '9':
335                 position = length * (key-'0')/10.0;
336                 break;
337         case UP:      position += 60.0;                 break;
338         case DOWN:    position -= 60.0;                 break;
339         case LEFT:    position -= 10.0;                 break;
340         case RIGHT:   position += 10.0;                 break;
341         case KPSTOP:  next_command = STOP;              break;
342         case KPREV:   next_command = NORMAL_REWIND;     break;
343         case KPPLAY:  next_command = NORMAL_FWD;        break;
344         case KPBACK:  next_command = FAST_REWIND;       break;
345         case KPFWRD:  next_command = FAST_FWD;          break;
346         case KPRECD:  next_command = SLOW_REWIND;       break;
347         case KPAUSE:  next_command = SLOW_FWD;          break;
348         case ' ':  next_command = NORMAL_FWD;           break;
349         case 'a':  gui->tile_windows(0);                return 1;
350         case 'b':  gui->tile_windows(1);                return 1;
351         case 'c':  gui->tile_windows(2);                return 1;
352 #ifdef HAVE_DVB
353         case 'd':
354                 mwindow_gui->channel_info->toggle_scan();
355                 return 1;
356 #endif
357         case 'e':
358                 break;
359         case 'f': {
360                 Canvas *canvas = mwindow_gui->mwindow->cwindow->gui->canvas;
361                 if( !canvas->get_fullscreen() )
362                         canvas->start_fullscreen();
363                 else
364                         canvas->stop_fullscreen();
365                 return 1; }
366         default:
367                 return -1;
368         }
369
370         if( next_command < 0 ) {
371                 if( position < 0 ) position = 0;
372                 transport->change_position(position);
373         }
374         else
375                 transport->handle_transport(next_command, 0, 0);
376         return 1;
377 }
378