4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
25 #include "awindowgui.h"
32 #include "edlsession.h"
33 #include "filesystem.h"
39 #include "localsession.h"
40 #include "mainclock.h"
42 #include "mainsession.h"
44 #include "meterpanel.h"
45 #include "mwindowgui.h"
47 #include "playtransport.h"
48 #include "preferences.h"
49 #include "renderengine.h"
54 #include "transportque.h"
56 #include "vplayback.h"
58 #include "vwindowgui.h"
64 VWindowGUI::VWindowGUI(MWindow *mwindow, VWindow *vwindow)
65 : BC_Window(_(PROGRAM_NAME ": Viewer"),
66 mwindow->session->vwindow_x,
67 mwindow->session->vwindow_y,
68 mwindow->session->vwindow_w,
69 mwindow->session->vwindow_h,
76 this->mwindow = mwindow;
77 this->vwindow = vwindow;
83 strcpy(loaded_title, "");
87 VWindowGUI::~VWindowGUI()
89 vwindow->playback_engine->interrupt_playback(1);
90 sources.remove_all_objects();
91 labels.remove_all_objects();
99 void VWindowGUI::draw_wave()
101 TransportCommand command;
102 command.command = NORMAL_FWD;
103 command.get_edl()->copy_all(vwindow->get_edl());
104 command.change_type = CHANGE_ALL;
105 command.realtime = 0;
106 RenderEngine *render_engine = new RenderEngine(0, mwindow->preferences, 0, 0);
107 CICache *cache = new CICache(mwindow->preferences);
108 render_engine->set_acache(cache);
109 render_engine->arm_command(&command);
111 double duration = 1.;
112 int w = mwindow->edl->session->output_w;
113 int h = mwindow->edl->session->output_h;
114 VFrame *vframe = new VFrame(w, h, BC_RGB888);
115 int sample_rate = mwindow->edl->get_sample_rate();
116 int channels = mwindow->edl->session->audio_channels;
117 if( channels > 2 ) channels = 2;
118 int64_t bfrsz = sample_rate * duration;
119 Samples *samples[MAXCHANNELS];
121 while( ch < channels ) samples[ch++] = new Samples(bfrsz);
122 while( ch < MAXCHANNELS ) samples[ch++] = 0;
123 render_engine->arender->process_buffer(samples, bfrsz, 0);
125 static int line_colors[2] = { GREEN, YELLOW };
126 static int base_colors[2] = { RED, PINK };
127 for( int i=channels; --i>=0; ) {
128 AssetPicon::draw_wave(vframe, samples[i]->get_data(), bfrsz,
129 base_colors[i], line_colors[i]);
132 for( int i=channels; --i>=0; ) delete samples[i];
133 delete render_engine;
135 delete canvas->refresh_frame;
136 canvas->refresh_frame = vframe;
137 canvas->draw_refresh(1);
140 void VWindowGUI::change_source(EDL *edl, const char *title)
142 //printf("VWindowGUI::change_source %d\n", __LINE__);
144 update_sources(title);
145 strcpy(loaded_title, title);
146 char string[BCTEXTLEN];
148 sprintf(string, _(PROGRAM_NAME ": %s"), title);
150 sprintf(string, _(PROGRAM_NAME ": Viewer"));
152 lock_window("VWindowGUI::change_source");
155 !edl->tracks->playable_video_tracks() &&
156 edl->tracks->playable_audio_tracks() )
164 // Get source list from master EDL
165 void VWindowGUI::update_sources(const char *title)
167 lock_window("VWindowGUI::update_sources");
168 sources.remove_all_objects();
170 for( int i=0; i<mwindow->edl->clips.size(); ++i ) {
171 char *clip_title = mwindow->edl->clips.values[i]->local_session->clip_title;
174 for( int j=0; !exists && j<sources.size(); ++j ) {
175 if( !strcasecmp(sources.values[j]->get_text(), clip_title) )
180 sources.append(new BC_ListBoxItem(clip_title));
184 for( Asset *current=mwindow->edl->assets->first; current; current=NEXT ) {
185 char clip_title[BCTEXTLEN];
186 fs.extract_name(clip_title, current->path);
189 for( int j=0; !exists && j<sources.size(); ++j ) {
190 if( !strcasecmp(sources.values[j]->get_text(), clip_title) )
195 sources.append(new BC_ListBoxItem(clip_title));
201 void VWindowGUI::create_objects()
205 lock_window("VWindowGUI::create_objects");
206 set_icon(mwindow->theme->get_image("vwindow_icon"));
208 //printf("VWindowGUI::create_objects 1\n");
209 mwindow->theme->get_vwindow_sizes(this);
210 mwindow->theme->draw_vwindow_bg(this);
213 meters = new VWindowMeters(mwindow,
215 mwindow->theme->vmeter_x,
216 mwindow->theme->vmeter_y,
217 mwindow->theme->vmeter_h);
218 meters->create_objects();
220 //printf("VWindowGUI::create_objects 1\n");
221 // Requires meters to build
222 edit_panel = new VWindowEditing(mwindow, vwindow);
223 edit_panel->set_meters(meters);
224 edit_panel->create_objects();
226 //printf("VWindowGUI::create_objects 1\n");
227 transport = new VWindowTransport(mwindow,
229 mwindow->theme->vtransport_x,
230 mwindow->theme->vtransport_y);
231 transport->create_objects();
233 //printf("VWindowGUI::create_objects 1\n");
234 // add_subwindow(fps_title = new BC_Title(mwindow->theme->vedit_x, y, ""));
235 add_subwindow(clock = new MainClock(mwindow,
236 mwindow->theme->vtime_x,
237 mwindow->theme->vtime_y,
238 mwindow->theme->vtime_w));
240 canvas = new VWindowCanvas(mwindow, this);
241 canvas->create_objects(mwindow->edl);
242 canvas->use_vwindow();
245 //printf("VWindowGUI::create_objects 1\n");
246 add_subwindow(timebar = new VTimeBar(mwindow,
248 mwindow->theme->vtimebar_x,
249 mwindow->theme->vtimebar_y,
250 mwindow->theme->vtimebar_w,
251 mwindow->theme->vtimebar_h));
252 timebar->create_objects();
253 //printf("VWindowGUI::create_objects 2\n");
256 //printf("VWindowGUI::create_objects 1\n");
257 // source = new VWindowSource(mwindow,
259 // mwindow->theme->vsource_x,
260 // mwindow->theme->vsource_y);
261 // source->create_objects();
262 update_sources(_("None"));
264 //printf("VWindowGUI::create_objects 2\n");
271 int VWindowGUI::resize_event(int w, int h)
273 mwindow->session->vwindow_x = get_x();
274 mwindow->session->vwindow_y = get_y();
275 mwindow->session->vwindow_w = w;
276 mwindow->session->vwindow_h = h;
278 mwindow->theme->get_vwindow_sizes(this);
279 mwindow->theme->draw_vwindow_bg(this);
282 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vedit_y);
283 edit_panel->reposition_buttons(mwindow->theme->vedit_x,
284 mwindow->theme->vedit_y);
286 timebar->resize_event();
287 transport->reposition_buttons(mwindow->theme->vtransport_x,
288 mwindow->theme->vtransport_y);
289 clock->reposition_window(mwindow->theme->vtime_x,
290 mwindow->theme->vtime_y,
291 mwindow->theme->vtime_w,
293 canvas->reposition_window(0,
294 mwindow->theme->vcanvas_x,
295 mwindow->theme->vcanvas_y,
296 mwindow->theme->vcanvas_w,
297 mwindow->theme->vcanvas_h);
298 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
299 // source->reposition_window(mwindow->theme->vsource_x,
300 // mwindow->theme->vsource_y);
301 meters->reposition_window(mwindow->theme->vmeter_x,
302 mwindow->theme->vmeter_y,
304 mwindow->theme->vmeter_h);
306 BC_WindowBase::resize_event(w, h);
314 int VWindowGUI::translation_event()
316 mwindow->session->vwindow_x = get_x();
317 mwindow->session->vwindow_y = get_y();
321 int VWindowGUI::close_event()
324 int i = mwindow->vwindows.size();
325 while( --i >= 0 && mwindow->vwindows.get(i)->gui != this );
331 mwindow->session->show_vwindow = 0;
334 mwindow->gui->lock_window("VWindowGUI::close_event");
335 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
336 mwindow->gui->unlock_window();
338 lock_window("VWindowGUI::close_event");
339 mwindow->save_defaults();
343 int VWindowGUI::keypress_event()
346 switch(get_keypress())
354 mwindow->undo_entry(this);
357 mwindow->redo_entry(this);
361 if(mwindow->session->vwindow_fullscreen)
362 canvas->stop_fullscreen();
364 canvas->start_fullscreen();
365 lock_window("VWindowGUI::keypress_event 1");
369 if(mwindow->session->vwindow_fullscreen)
370 canvas->stop_fullscreen();
371 lock_window("VWindowGUI::keypress_event 2");
374 if(!result) result = transport->keypress_event();
378 void VWindowGUI::stop_transport(const char *lock_msg)
380 if( !transport->is_stopped() ) {
381 if( lock_msg ) unlock_window();
382 transport->handle_transport(STOP, 1, 0, 0);
383 if( lock_msg ) lock_window(lock_msg);
387 int VWindowGUI::button_press_event()
389 if( vwindow->get_edl() != 0 && canvas->get_canvas() &&
390 mwindow->edl->session->vwindow_click2play &&
391 canvas->get_canvas()->get_cursor_over_window() ) {
392 switch( get_buttonpress() ) {
394 if( !vwindow->playback_engine->is_playing_back ) {
395 double length = vwindow->get_edl()->tracks->total_playable_length();
396 double position = vwindow->playback_engine->get_tracking_position();
397 if( position >= length ) transport->goto_start();
399 return transport->forward_play->handle_event();
401 if( !vwindow->playback_engine->is_playing_back ) {
402 double position = vwindow->playback_engine->get_tracking_position();
403 if( position <= 0 ) transport->goto_end();
405 return transport->reverse_play->handle_event();
406 case RIGHT_BUTTON: // activates popup
409 return transport->frame_forward_play->handle_event();
411 return transport->frame_reverse_play->handle_event();
414 if(canvas->get_canvas())
415 return canvas->button_press_event_base(canvas->get_canvas());
419 int VWindowGUI::cursor_leave_event()
421 if(canvas->get_canvas())
422 return canvas->cursor_leave_event_base(canvas->get_canvas());
426 int VWindowGUI::cursor_enter_event()
428 if(canvas->get_canvas())
429 return canvas->cursor_enter_event_base(canvas->get_canvas());
433 int VWindowGUI::button_release_event()
435 if(canvas->get_canvas())
436 return canvas->button_release_event();
440 int VWindowGUI::cursor_motion_event()
442 if(canvas->get_canvas())
444 canvas->get_canvas()->unhide_cursor();
445 return canvas->cursor_motion_event();
451 void VWindowGUI::drag_motion()
454 if(get_hidden()) return;
455 if(mwindow->session->current_operation != DRAG_ASSET) return;
456 int need_highlight = cursor_above() && get_cursor_over_window() ? 1 : 0;
457 if( highlighted == need_highlight ) return;
458 highlighted = need_highlight;
459 canvas->draw_refresh();
462 int VWindowGUI::drag_stop()
464 if(get_hidden()) return 0;
467 mwindow->session->current_operation == DRAG_ASSET)
470 canvas->draw_refresh();
473 Indexable *indexable = mwindow->session->drag_assets->size() ?
474 mwindow->session->drag_assets->get(0) :
476 EDL *edl = mwindow->session->drag_clips->size() ?
477 mwindow->session->drag_clips->get(0) :
480 vwindow->change_source(indexable);
483 vwindow->change_source(edl);
484 lock_window("VWindowGUI::drag_stop");
492 void VWindowGUI::update_meters()
494 if(mwindow->edl->session->vwindow_meter != meters->visible)
496 meters->set_meters(meters->meter_count,
497 mwindow->edl->session->vwindow_meter);
498 mwindow->theme->get_vwindow_sizes(this);
499 resize_event(get_w(), get_h());
505 VWindowMeters::VWindowMeters(MWindow *mwindow,
510 : MeterPanel(mwindow,
516 mwindow->edl->session->audio_channels,
517 mwindow->edl->session->vwindow_meter,
521 this->mwindow = mwindow;
525 VWindowMeters::~VWindowMeters()
529 int VWindowMeters::change_status_event(int new_status)
531 mwindow->edl->session->vwindow_meter = new_status;
532 gui->update_meters();
537 VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
538 : EditPanel(mwindow, vwindow->gui, VWINDOW_ID,
539 mwindow->theme->vedit_x, mwindow->theme->vedit_y,
541 0, // use_editing_mode
560 this->mwindow = mwindow;
561 this->vwindow = vwindow;
564 VWindowEditing::~VWindowEditing()
568 void VWindowEditing::copy_selection()
573 void VWindowEditing::splice_selection()
575 if(vwindow->get_edl())
577 mwindow->gui->lock_window("VWindowEditing::splice_selection");
578 mwindow->splice(vwindow->get_edl());
579 mwindow->gui->unlock_window();
583 void VWindowEditing::overwrite_selection()
585 if(vwindow->get_edl())
587 mwindow->gui->lock_window("VWindowEditing::overwrite_selection");
588 mwindow->overwrite(vwindow->get_edl());
589 mwindow->gui->unlock_window();
593 void VWindowEditing::toggle_label()
595 if(vwindow->get_edl())
597 EDL *edl = vwindow->get_edl();
598 edl->labels->toggle_label(edl->local_session->get_selectionstart(1),
599 edl->local_session->get_selectionend(1));
600 vwindow->gui->timebar->update(1);
604 void VWindowEditing::prev_label()
606 if(vwindow->get_edl())
608 EDL *edl = vwindow->get_edl();
609 vwindow->gui->unlock_window();
610 vwindow->playback_engine->interrupt_playback(1);
611 vwindow->gui->lock_window("VWindowEditing::prev_label");
613 Label *current = edl->labels->prev_label(
614 edl->local_session->get_selectionstart(1));
619 edl->local_session->set_selectionstart(0);
620 edl->local_session->set_selectionend(0);
621 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
622 vwindow->gui->timebar->update(1);
626 edl->local_session->set_selectionstart(current->position);
627 edl->local_session->set_selectionend(current->position);
628 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
629 vwindow->gui->timebar->update(1);
634 void VWindowEditing::next_label()
636 if(vwindow->get_edl())
638 EDL *edl = vwindow->get_edl();
639 Label *current = edl->labels->next_label(
640 edl->local_session->get_selectionstart(1));
643 vwindow->gui->unlock_window();
644 vwindow->playback_engine->interrupt_playback(1);
645 vwindow->gui->lock_window("VWindowEditing::next_label 1");
647 double position = edl->tracks->total_length();
648 edl->local_session->set_selectionstart(position);
649 edl->local_session->set_selectionend(position);
650 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
651 vwindow->gui->timebar->update(1);
655 vwindow->gui->unlock_window();
656 vwindow->playback_engine->interrupt_playback(1);
657 vwindow->gui->lock_window("VWindowEditing::next_label 2");
659 edl->local_session->set_selectionstart(current->position);
660 edl->local_session->set_selectionend(current->position);
661 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
662 vwindow->gui->timebar->update(1);
667 double VWindowEditing::get_position()
669 EDL *edl = vwindow->get_edl();
670 double position = !edl ? 0 : edl->local_session->get_selectionstart(1);
674 void VWindowEditing::set_position(double position)
676 EDL *edl = vwindow->get_edl();
678 if( get_position() != position ) {
679 if( position < 0 ) position = 0;
680 edl->local_session->set_selectionstart(position);
681 edl->local_session->set_selectionend(position);
682 vwindow->update_position(CHANGE_NONE, 0, 1);
686 void VWindowEditing::set_inpoint()
688 vwindow->set_inpoint();
691 void VWindowEditing::set_outpoint()
693 vwindow->set_outpoint();
696 void VWindowEditing::unset_inoutpoint()
698 vwindow->unset_inoutpoint();
702 void VWindowEditing::to_clip()
704 EDL *edl = vwindow->get_edl();
706 mwindow->to_clip(edl, _("viewer window: "));
709 VWindowSource::VWindowSource(MWindow *mwindow, VWindowGUI *vwindow, int x, int y)
710 : BC_PopupTextBox(vwindow,
718 this->mwindow = mwindow;
719 this->vwindow = vwindow;
722 VWindowSource::~VWindowSource()
726 int VWindowSource::handle_event()
732 VWindowTransport::VWindowTransport(MWindow *mwindow,
736 : PlayTransport(mwindow,
744 EDL* VWindowTransport::get_edl()
746 return gui->vwindow->get_edl();
750 void VWindowTransport::goto_start()
752 gui->unlock_window();
753 handle_transport(REWIND, 1);
754 gui->lock_window("VWindowTransport::goto_start");
755 gui->vwindow->goto_start();
758 void VWindowTransport::goto_end()
760 gui->unlock_window();
761 handle_transport(GOTO_END, 1);
762 gui->lock_window("VWindowTransport::goto_end");
763 gui->vwindow->goto_end();
769 VWindowCanvas::VWindowCanvas(MWindow *mwindow, VWindowGUI *gui)
772 mwindow->theme->vcanvas_x,
773 mwindow->theme->vcanvas_y,
774 mwindow->theme->vcanvas_w,
775 mwindow->theme->vcanvas_h,
778 //printf("VWindowCanvas::VWindowCanvas %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
779 this->mwindow = mwindow;
783 void VWindowCanvas::zoom_resize_window(float percentage)
785 EDL *edl = gui->vwindow->get_edl();
786 if(!edl) edl = mwindow->edl;
788 int canvas_w, canvas_h;
791 // Get required canvas size
792 calculate_sizes(edl->get_aspect_ratio(),
793 edl->session->output_w,
794 edl->session->output_h,
799 // Estimate window size from current borders
800 new_w = canvas_w + (gui->get_w() - mwindow->theme->vcanvas_w);
801 new_h = canvas_h + (gui->get_h() - mwindow->theme->vcanvas_h);
803 mwindow->session->vwindow_w = new_w;
804 mwindow->session->vwindow_h = new_h;
806 mwindow->theme->get_vwindow_sizes(gui);
808 // Estimate again from new borders
809 new_w = canvas_w + (mwindow->session->vwindow_w - mwindow->theme->vcanvas_w);
810 new_h = canvas_h + (mwindow->session->vwindow_h - mwindow->theme->vcanvas_h);
813 gui->resize_window(new_w, new_h);
814 gui->resize_event(new_w, new_h);
817 void VWindowCanvas::close_source()
819 gui->unlock_window();
820 gui->vwindow->playback_engine->interrupt_playback(1);
821 gui->lock_window("VWindowCanvas::close_source");
822 gui->vwindow->delete_source(1, 1);
826 void VWindowCanvas::draw_refresh(int flush)
828 EDL *edl = gui->vwindow->get_edl();
830 if(!get_canvas()->get_video_on()) get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
831 if(!get_canvas()->get_video_on() && refresh_frame && edl)
833 float in_x1, in_y1, in_x2, in_y2;
834 float out_x1, out_y1, out_x2, out_y2;
844 get_canvas()->draw_vframe(refresh_frame,
847 (int)(out_x2 - out_x1),
848 (int)(out_y2 - out_y1),
851 (int)(in_x2 - in_x1),
852 (int)(in_y2 - in_y1),
856 if(!get_canvas()->get_video_on())
859 get_canvas()->flash(flush);
863 void VWindowCanvas::draw_overlays()
865 if( gui->highlighted )
867 get_canvas()->set_color(WHITE);
868 get_canvas()->set_inverse();
869 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
870 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
871 get_canvas()->set_opaque();
875 int VWindowCanvas::get_fullscreen()
877 return mwindow->session->vwindow_fullscreen;
880 void VWindowCanvas::set_fullscreen(int value)
882 mwindow->session->vwindow_fullscreen = value;