4 * Copyright (C) 1997-2012 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
24 #include "cwindowgui.h"
28 #include "edlsession.h"
29 #include "formatpresets.h"
31 #include "levelwindow.h"
32 #include "levelwindowgui.h"
33 #include "mainerror.h"
37 #include "mwindowgui.h"
39 #include "preferences.h"
40 #include "rotateframe.h"
41 #include "setformat.h"
45 #include "vwindowgui.h"
49 SetFormat::SetFormat(MWindow *mwindow)
50 : BC_MenuItem(_("Format..."), _("Shift-F"), 'F')
53 this->mwindow = mwindow;
54 thread = new SetFormatThread(mwindow);
57 SetFormat::~SetFormat()
62 int SetFormat::handle_event()
64 if(!thread->running())
70 // window_lock has to be locked but window can't be locked until after
71 // it is known to exist, so we neglect window_lock for now
74 thread->window_lock->lock("SetFormat::handle_event");
75 thread->window->lock_window("SetFormat::handle_event");
76 thread->window->raise_window();
77 thread->window->unlock_window();
78 thread->window_lock->unlock();
84 SetFormatThread::SetFormatThread(MWindow *mwindow)
87 this->mwindow = mwindow;
88 window_lock = new Mutex("SetFormatThread::window_lock");
92 SetFormatThread::~SetFormatThread()
102 void SetFormatThread::run()
104 orig_dimension[0] = dimension[0] = mwindow->edl->session->output_w;
105 orig_dimension[1] = dimension[1] = mwindow->edl->session->output_h;
106 auto_aspect = mwindow->defaults->get("AUTOASPECT", 0);
108 ratio[0] = ratio[1] = 1;
110 new_settings = new EDL;
111 new_settings->create_objects();
112 new_settings->copy_session(mwindow->edl);
114 // This locks mwindow, so it must be done outside window_lock
115 int x = mwindow->gui->get_abs_cursor_x(1) - mwindow->theme->setformat_w / 2;
116 int y = mwindow->gui->get_abs_cursor_y(1) - mwindow->theme->setformat_h / 2;
118 window_lock->lock("SetFormatThread::run 1");
119 window = new SetFormatWindow(mwindow, this, x, y);
120 window->create_objects();
121 window_lock->unlock();
123 int result = window->run_window();
126 window_lock->lock("SetFormatThread::run 2");
129 window_lock->unlock();
137 mwindow->defaults->update("AUTOASPECT", auto_aspect);
138 new_settings->Garbage::remove_user();
141 void SetFormatThread::apply_changes()
143 double new_samplerate = new_settings->session->sample_rate;
144 double old_samplerate = mwindow->edl->session->sample_rate;
145 double new_framerate = new_settings->session->frame_rate;
146 double old_framerate = mwindow->edl->session->frame_rate;
147 int new_channels = new_settings->session->audio_channels;
148 CLAMP(new_channels, 1, MAXCHANNELS);
152 mwindow->undo->update_undo_before();
154 memcpy(&mwindow->preferences->channel_positions[new_channels - 1],
155 new_settings->session->achannel_positions,
156 sizeof(mwindow->preferences->channel_positions[new_channels - 1]));
159 mwindow->edl->copy_session(new_settings, 1);
160 mwindow->edl->session->output_w = dimension[0];
161 mwindow->edl->session->output_h = dimension[1];
162 mwindow->edl->retrack();
163 mwindow->edl->rechannel();
164 mwindow->edl->resample(old_samplerate, new_samplerate, TRACK_AUDIO);
165 mwindow->edl->resample(old_framerate, new_framerate, TRACK_VIDEO);
166 mwindow->save_backup();
167 mwindow->undo->update_undo_after(_("set format"), LOAD_ALL);
169 mwindow->resync_guis();
172 void SetFormatThread::update()
174 window->sample_rate->update(new_settings->session->sample_rate);
175 window->channels->update((int64_t)new_settings->session->audio_channels);
176 window->frame_rate->update((float)new_settings->session->frame_rate);
179 window->auto_aspect->update(0);
182 dimension[0] = new_settings->session->output_w;
183 window->dimension[0]->update((int64_t)dimension[0]);
184 dimension[1] = new_settings->session->output_h;
185 window->dimension[1]->update((int64_t)dimension[1]);
187 ratio[0] = (float)dimension[0] / orig_dimension[0];
188 window->ratio[0]->update(ratio[0]);
189 ratio[1] = (float)dimension[1] / orig_dimension[1];
190 window->ratio[1]->update(ratio[1]);
192 window->aspect_w->update(new_settings->session->aspect_w);
193 window->aspect_h->update(new_settings->session->aspect_h);
194 window->interlace_pulldown->update(new_settings->session->interlace_mode);
195 window->color_model->update_value(new_settings->session->color_model);
197 window->canvas->draw();
200 void SetFormatThread::update_window()
202 int i, result, modified_item = 0, dimension_modified = 0, ratio_modified = 0;
204 for(i = 0, result = 0; i < 2 && !result; i++)
211 dimension_modified = 1;
224 if(dimension_modified)
225 ratio[modified_item] = (float)dimension[modified_item] / orig_dimension[modified_item];
227 if(ratio_modified && !constrain_ratio)
229 dimension[modified_item] = (int)(orig_dimension[modified_item] * ratio[modified_item]);
230 window->dimension[modified_item]->update((int64_t)dimension[modified_item]);
233 for(i = 0; i < 2; i++)
235 if(dimension_modified ||
236 (i != modified_item && ratio_modified))
238 if(constrain_ratio) ratio[i] = ratio[modified_item];
239 window->ratio[i]->update(ratio[i]);
243 (i != modified_item && dimension_modified))
247 dimension[i] = (int)(orig_dimension[i] * ratio[modified_item]);
248 window->dimension[i]->update((int64_t)dimension[i]);
257 void SetFormatThread::update_aspect()
261 char string[BCTEXTLEN];
262 MWindow::create_aspect_ratio(new_settings->session->aspect_w,
263 new_settings->session->aspect_h,
266 sprintf(string, "%.02f", new_settings->session->aspect_w);
267 window->aspect_w->update(string);
268 sprintf(string, "%.02f", new_settings->session->aspect_h);
269 window->aspect_h->update(string);
281 SetFormatWindow::SetFormatWindow(MWindow *mwindow,
282 SetFormatThread *thread, int x, int y)
283 : BC_Window(_(PROGRAM_NAME ": Set Format"), x, y,
284 mwindow->theme->setformat_w, mwindow->theme->setformat_h,
287 this->mwindow = mwindow;
288 this->thread = thread;
291 SetFormatWindow::~SetFormatWindow()
296 void SetFormatWindow::create_objects()
298 lock_window("SetFormatWindow::create_objects");
299 int x = 10, y = mwindow->theme->setformat_y1;
302 mwindow->theme->draw_setformat_bg(this);
304 presets = new SetFormatPresets(mwindow, this, x, y);
305 presets->create_objects();
306 x = presets->x; // y = presets->y;
307 y = mwindow->theme->setformat_y2;
309 add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
310 _("Audio"), LARGEFONT));
311 y = mwindow->theme->setformat_y3;
313 add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
315 add_subwindow(sample_rate = new SetSampleRateTextBox(thread,
316 mwindow->theme->setformat_x2,
318 add_subwindow(new SampleRatePulldown(mwindow, sample_rate,
319 mwindow->theme->setformat_x2 + sample_rate->get_w(), y));
321 y += mwindow->theme->setformat_margin;
322 add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
324 add_subwindow(channels = new SetChannelsTextBox(thread,
325 mwindow->theme->setformat_x2, y));
326 add_subwindow(new BC_ITumbler(channels, 1, MAXCHANNELS,
327 mwindow->theme->setformat_x2 + channels->get_w(), y));
329 y += mwindow->theme->setformat_margin;
330 add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
331 _("Channel positions:")));
332 y += mwindow->theme->setformat_margin;
333 add_subwindow(new SetChannelsReset(thread,
334 mwindow->theme->setformat_x1, y,
336 add_subwindow(canvas = new SetChannelsCanvas(mwindow,
338 mwindow->theme->setformat_channels_x,
339 mwindow->theme->setformat_channels_y,
340 mwindow->theme->setformat_channels_w,
341 mwindow->theme->setformat_channels_h));
346 y = mwindow->theme->setformat_y2;
347 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
352 y = mwindow->theme->setformat_y3;
353 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
356 add_subwindow(frame_rate = new SetFrameRateTextBox(thread,
357 mwindow->theme->setformat_x4,
359 add_subwindow(new FrameRatePulldown(mwindow,
361 mwindow->theme->setformat_x4 + frame_rate->get_w(),
364 y += mwindow->theme->setformat_margin;
365 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
369 y += mwindow->theme->setformat_margin;
370 add_subwindow(title = new BC_Title(mwindow->theme->setformat_x3, y, _("Width:")));
371 add_subwindow(dimension[0] = new ScaleSizeText(mwindow->theme->setformat_x4,
374 &(thread->dimension[0])));
376 y += mwindow->theme->setformat_margin;
377 add_subwindow(new BC_Title(mwindow->theme->setformat_x3, y, _("Height:")));
378 add_subwindow(dimension[1] = new ScaleSizeText(mwindow->theme->setformat_x4,
381 &(thread->dimension[1])));
383 x = mwindow->theme->setformat_x4 + dimension[0]->get_w();
384 FrameSizePulldown *pulldown;
385 add_subwindow(pulldown = new FrameSizePulldown(mwindow->theme,
389 y - mwindow->theme->setformat_margin));
391 add_subwindow(new FormatSwapExtents(mwindow,
394 x + pulldown->get_w() + 5,
395 y - mwindow->theme->setformat_margin));
397 y += mwindow->theme->setformat_margin;
398 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
401 add_subwindow(ratio[0] = new ScaleRatioText(mwindow->theme->setformat_x4,
404 &(thread->ratio[0])));
406 y += mwindow->theme->setformat_margin;
407 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
410 add_subwindow(ratio[1] = new ScaleRatioText(mwindow->theme->setformat_x4,
413 &(thread->ratio[1])));
415 y += mwindow->theme->setformat_margin;
416 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
419 x = mwindow->theme->setformat_x4;
420 add_subwindow(textbox = new BC_TextBox(x,
425 x += textbox->get_w();
426 add_subwindow(color_model = new ColormodelPulldown(mwindow,
428 &thread->new_settings->session->color_model,
432 y += mwindow->theme->setformat_margin;
433 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
435 _("Aspect ratio:")));
436 y += mwindow->theme->setformat_margin;
437 x = mwindow->theme->setformat_x3;
438 add_subwindow(aspect_w = new ScaleAspectText(x,
441 &(thread->new_settings->session->aspect_w)));
442 x += aspect_w->get_w() + 5;
443 add_subwindow(new BC_Title(x, y, ":"));
445 add_subwindow(aspect_h = new ScaleAspectText(x,
448 &(thread->new_settings->session->aspect_h)));
449 x += aspect_h->get_w();
450 add_subwindow(new AspectPulldown(mwindow,
456 add_subwindow(auto_aspect = new ScaleAspectAuto(x, y, thread));
457 y += mwindow->theme->setformat_margin;
459 // --------------------
460 add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
462 _("Interlace mode:")));
463 add_subwindow(textbox = new BC_TextBox(mwindow->theme->setformat_x4,
468 add_subwindow(interlace_pulldown = new InterlacemodePulldown(mwindow,
470 &(thread->new_settings->session->interlace_mode),
471 (ArrayList<BC_ListBoxItem*>*)&mwindow->interlace_project_modes,
472 mwindow->theme->setformat_x4 + textbox->get_w(),
474 y += mwindow->theme->setformat_margin;
478 BC_CancelTextButton *cancel;
479 add_subwindow(ok = new BC_OKTextButton(this));
480 add_subwindow(cancel = new BC_CancelTextButton(this));
481 add_subwindow(new SetFormatApply((ok->get_x() + cancel->get_x()) / 2,
489 const char* SetFormatWindow::get_preset_text()
495 SetFormatPresets::SetFormatPresets(MWindow *mwindow,
496 SetFormatWindow *gui,
499 : FormatPresets(mwindow, 0, gui, x, y)
504 SetFormatPresets::~SetFormatPresets()
508 int SetFormatPresets::handle_event()
510 format_gui->thread->update();
514 EDL* SetFormatPresets::get_edl()
516 return format_gui->thread->new_settings;
521 SetSampleRateTextBox::SetSampleRateTextBox(SetFormatThread *thread, int x, int y)
522 : BC_TextBox(x, y, 100, 1, (int64_t)thread->new_settings->session->sample_rate)
524 this->thread = thread;
526 int SetSampleRateTextBox::handle_event()
528 thread->new_settings->session->sample_rate = CLIP(atol(get_text()), 1, 1000000);
532 SetChannelsTextBox::SetChannelsTextBox(SetFormatThread *thread, int x, int y)
533 : BC_TextBox(x, y, 100, 1, thread->new_settings->session->audio_channels)
535 this->thread = thread;
537 int SetChannelsTextBox::handle_event()
539 int new_channels = CLIP(atoi(get_text()), 1, MAXCHANNELS);
541 thread->new_settings->session->audio_channels = new_channels;
546 memcpy(thread->new_settings->session->achannel_positions,
547 &thread->mwindow->preferences->channel_positions[new_channels - 1],
548 sizeof(thread->new_settings->session->achannel_positions));
552 thread->window->canvas->draw();
556 SetChannelsReset::SetChannelsReset(SetFormatThread *thread, int x, int y, const char *text)
557 : BC_GenericButton(x, y, text)
559 this->thread = thread;
562 int SetChannelsReset::handle_event()
564 int channels = thread->new_settings->session->audio_channels;
565 int *achannels = thread->new_settings->session->achannel_positions;
566 for( int i=0; i<MAX_CHANNELS; ++i )
567 achannels[i] = default_audio_channel_position(i, channels);
568 thread->window->canvas->draw();
572 SetChannelsCanvas::SetChannelsCanvas(MWindow *mwindow,
573 SetFormatThread *thread, int x, int y, int w, int h)
574 : BC_SubWindow(x, y, w, h)
576 this->thread = thread;
577 this->mwindow = mwindow;
579 box_r = mwindow->theme->channel_position_data->get_w() / 2;
580 temp_picon = new VFrame(
581 mwindow->theme->channel_position_data->get_w(),
582 mwindow->theme->channel_position_data->get_h(),
583 mwindow->theme->channel_position_data->get_color_model(),
585 rotater = new RotateFrame(mwindow->preferences->processors,
586 mwindow->theme->channel_position_data->get_w(),
587 mwindow->theme->channel_position_data->get_h());
589 SetChannelsCanvas::~SetChannelsCanvas()
595 int SetChannelsCanvas::draw(int angle)
598 //int real_w = get_w() - box_r * 2;
599 //int real_h = get_h() - box_r * 2;
600 //int real_x = box_r;
601 //int real_y = box_r;
603 draw_top_background(get_top_level(), 0, 0, get_w(), get_h());
604 // draw_vframe(mwindow->theme->channel_bg_data, 0, 0);
611 set_color(mwindow->theme->channel_position_color);
612 for(int i = 0; i < thread->new_settings->session->audio_channels; i++)
614 get_dimensions(thread->new_settings->session->achannel_positions[i],
619 double rotate_angle = thread->new_settings->session->achannel_positions[i];
620 rotate_angle = -rotate_angle;
621 while(rotate_angle < 0) rotate_angle += 360;
622 rotater->rotate(temp_picon,
623 mwindow->theme->channel_position_data,
627 BC_Pixmap temp_pixmap(this,
631 draw_pixmap(&temp_pixmap, x, y);
632 sprintf(string, "%d", i + 1);
633 draw_text(x + 2, y + box_r * 2 - 2, string);
638 sprintf(string, _("%d degrees"), angle);
639 draw_text(this->get_w() / 2 - 40, this->get_h() / 2, string);
646 int SetChannelsCanvas::get_dimensions(int channel_position,
653 int real_w = this->get_w() - box_r * 2 - MARGIN;
654 int real_h = this->get_h() - box_r * 2 - MARGIN;
655 float corrected_position = channel_position;
656 if(corrected_position < 0) corrected_position += 360;
657 Units::polar_to_xy((float)corrected_position, real_w / 2, x, y);
658 x += real_w / 2 + MARGIN / 2;
659 y += real_h / 2 + MARGIN / 2;
665 int SetChannelsCanvas::button_press_event()
667 if(!cursor_inside()) return 0;
668 // get active channel
669 for( int i = 0; i < thread->new_settings->session->audio_channels; i++ ) {
671 get_dimensions(thread->new_settings->session->achannel_positions[i], x, y, w, h);
672 if( get_cursor_x() > x && get_cursor_y() > y &&
673 get_cursor_x() < x + w && get_cursor_y() < y + h ) {
675 degree_offset = (int)Units::xy_to_polar(get_cursor_x() - this->get_w() / 2, get_cursor_y() - this->get_h() / 2);
677 if(degree_offset >= 360) degree_offset -= 360;
678 degree_offset -= thread->new_settings->session->achannel_positions[i];
679 draw(thread->new_settings->session->achannel_positions[i]);
686 int SetChannelsCanvas::button_release_event()
688 if(active_channel >= 0)
697 int SetChannelsCanvas::cursor_motion_event()
699 if(active_channel >= 0)
701 // get degrees of new channel
703 new_d = (int)Units::xy_to_polar(get_cursor_x() - this->get_w() / 2, get_cursor_y() - this->get_h() / 2);
705 new_d -= degree_offset;
707 while(new_d >= 360) new_d -= 360;
708 while(new_d < 0) new_d += 360;
710 if(thread->new_settings->session->achannel_positions[active_channel] != new_d)
712 thread->new_settings->session->achannel_positions[active_channel] = new_d;
713 int new_channels = thread->new_settings->session->audio_channels;
714 memcpy(&thread->mwindow->preferences->channel_positions[new_channels - 1],
715 thread->new_settings->session->achannel_positions,
716 sizeof(thread->mwindow->preferences->channel_positions[new_channels - 1]));
717 draw(thread->new_settings->session->achannel_positions[active_channel]);
725 SetFrameRateTextBox::SetFrameRateTextBox(SetFormatThread *thread, int x, int y)
726 : BC_TextBox(x, y, 100, 1, (float)thread->new_settings->session->frame_rate)
728 this->thread = thread;
731 int SetFrameRateTextBox::handle_event()
733 thread->new_settings->session->frame_rate = Units::atoframerate(get_text());
739 // SetVChannels::SetVChannels(SetFormatThread *thread, int x, int y)
740 // : BC_TextBox(x, y, 100, 1, thread->channels)
742 // this->thread = thread;
744 // int SetVChannels::handle_event()
746 // thread->channels = atol(get_text());
753 ScaleSizeText::ScaleSizeText(int x, int y, SetFormatThread *thread, int *output)
754 : BC_TextBox(x, y, 100, 1, *output)
756 this->thread = thread;
757 this->output = output;
759 ScaleSizeText::~ScaleSizeText()
762 int ScaleSizeText::handle_event()
764 *output = atol(get_text());
767 if(*output <= 0) *output = 2;
768 if(*output > 10000) *output = 10000;
770 thread->update_window();
776 ScaleRatioText::ScaleRatioText(int x,
778 SetFormatThread *thread,
780 : BC_TextBox(x, y, 100, 1, *output)
782 this->thread = thread;
783 this->output = output;
785 ScaleRatioText::~ScaleRatioText()
788 int ScaleRatioText::handle_event()
790 *output = atof(get_text());
791 //if(*output <= 0) *output = 1;
792 if(*output > 10000) *output = 10000;
793 if(*output < -10000) *output = -10000;
795 thread->update_window();
800 ScaleAspectAuto::ScaleAspectAuto(int x, int y, SetFormatThread *thread)
801 : BC_CheckBox(x, y, thread->auto_aspect, _("Auto"))
803 this->thread = thread;
806 ScaleAspectAuto::~ScaleAspectAuto()
810 int ScaleAspectAuto::handle_event()
812 thread->auto_aspect = get_value();
813 thread->update_aspect();
817 ScaleAspectText::ScaleAspectText(int x, int y, SetFormatThread *thread, float *output)
818 : BC_TextBox(x, y, 70, 1, *output)
820 this->output = output;
821 this->thread = thread;
823 ScaleAspectText::~ScaleAspectText()
827 int ScaleAspectText::handle_event()
829 *output = atof(get_text());
834 SetFormatApply::SetFormatApply(int x, int y, SetFormatThread *thread)
835 : BC_GenericButton(x, y, _("Apply"))
837 this->thread = thread;
840 int SetFormatApply::handle_event()
842 thread->apply_changes();
847 FormatSwapExtents::FormatSwapExtents(MWindow *mwindow,
848 SetFormatThread *thread,
849 SetFormatWindow *gui,
852 : BC_Button(x, y, mwindow->theme->get_image_set("swap_extents"))
854 this->mwindow = mwindow;
855 this->thread = thread;
857 set_tooltip(_("Swap dimensions"));
860 int FormatSwapExtents::handle_event()
862 int w = thread->dimension[0];
863 int h = thread->dimension[1];
864 thread->dimension[0] = -h;
865 gui->dimension[0]->update((int64_t)h);
866 gui->dimension[1]->update((int64_t)w);
867 thread->update_window();
868 thread->dimension[1] = -w;
869 thread->update_window();