/////////////////////////////////////////////////////////////////////////////
// Name:        VideoPropDlg.cpp
// Purpose:     The video properties dialog
// Author:      Alex Thuering
// Created:     09.09.2010
// RCS-ID:      $Id: VideoPropDlg.cpp,v 1.15 2012/06/24 22:57:45 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#include "VideoPropDlg.h"
#include "DVD.h"
#include "Utils.h"
#include <wx/artprov.h>
#include <wx/regex.h>

// begin wxGlade: ::extracode

// end wxGlade
enum {
	DST_CHOICE_ID = 2000,
	INTERLACED_CHOICE_ID,
	FF_CHOICE_ID,
	ASPECT_CHOICE_ID,
	KEEP_ASPECT_CB_ID,
	BORDER_UP_CTRL_ID,
	BORDER_LEFT_CTRL_ID,
	BORDER_RIGHT_CTRL_ID,
	BORDER_DOWN_CTRL_ID,
	CROP_UP_CTRL_ID,
	CROP_LEFT_CTRL_ID,
	CROP_RIGHT_CTRL_ID,
	CROP_DOWN_CTRL_ID,
	SLIDER_ID,
	TIME_CTRL_ID,
	TIME_SPIN_BT_ID,
	START_BT_ID,
	END_BT_ID
};

BEGIN_EVENT_TABLE(VideoPropDlg, wxDialog)
    // begin wxGlade: VideoPropDlg::event_table
    EVT_CHOICE(DST_CHOICE_ID, VideoPropDlg::OnChangeFormat)
    EVT_CHOICE(ASPECT_CHOICE_ID, VideoPropDlg::OnChangeAspect)
    EVT_CHOICE(INTERLACED_CHOICE_ID, VideoPropDlg::OnInterlaced)
    EVT_CHECKBOX(KEEP_ASPECT_CB_ID, VideoPropDlg::OnChangeKeepAspect)
    EVT_SPINCTRL(BORDER_UP_CTRL_ID, VideoPropDlg::OnChangeBorder)
    EVT_SPINCTRL(BORDER_LEFT_CTRL_ID, VideoPropDlg::OnChangeBorder)
    EVT_SPINCTRL(BORDER_RIGHT_CTRL_ID, VideoPropDlg::OnChangeBorder)
    EVT_SPINCTRL(BORDER_DOWN_CTRL_ID, VideoPropDlg::OnChangeBorder)
    EVT_SPINCTRL(CROP_UP_CTRL_ID, VideoPropDlg::OnChangeCrop)
    EVT_SPINCTRL(CROP_LEFT_CTRL_ID, VideoPropDlg::OnChangeCrop)
    EVT_SPINCTRL(CROP_RIGHT_CTRL_ID, VideoPropDlg::OnChangeCrop)
    EVT_SPINCTRL(CROP_DOWN_CTRL_ID, VideoPropDlg::OnChangeCrop)
    EVT_COMMAND_SCROLL(SLIDER_ID, VideoPropDlg::OnSliderScroll)
    EVT_TEXT(TIME_CTRL_ID, VideoPropDlg::OnChangeTime)
    EVT_SPIN(TIME_SPIN_BT_ID, VideoPropDlg::OnTimeSpin)
    EVT_BUTTON(START_BT_ID, VideoPropDlg::OnStartBt)
    EVT_BUTTON(END_BT_ID, VideoPropDlg::OnEndBt)
    EVT_BUTTON(wxID_OK, VideoPropDlg::OnOkBt)
    // end wxGlade
END_EVENT_TABLE()

/**
 * Constructor
 */
VideoPropDlg::VideoPropDlg(wxWindow* parent, Vob* vob, AspectRatio aspectRatio):
		wxDialog(parent, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
	m_vob = vob;
	m_stream = vob->GetVideoStream();
	m_aspectRatio = aspectRatio;
	
    // begin wxGlade: VideoPropDlg::VideoPropDlg
    m_cropBox_staticbox = new wxStaticBox(this, -1, _("Crop"));
    m_padBox_staticbox = new wxStaticBox(this, -1, _("Border"));
    m_fileNameLabel = new wxStaticText(this, wxID_ANY, _("File Name:"));
    m_fileNameText = new wxStaticText(this, wxID_ANY, wxEmptyString);
    m_durLabel = new wxStaticText(this, wxID_ANY, _("Duration:"));
    m_durText = new wxStaticText(this, wxID_ANY, wxEmptyString);
    m_srcLabel = new wxStaticText(this, wxID_ANY, _("Source Format:"));
    m_srcText = new wxStaticText(this, wxID_ANY, wxEmptyString);
    m_dstLabel = new wxStaticText(this, wxID_ANY, _("Destination Format:"));
    const wxString *m_dstChoice_choices = NULL;
    m_dstChoice = new wxChoice(this, DST_CHOICE_ID, wxDefaultPosition, wxDefaultSize, 0, m_dstChoice_choices, 0);
    const wxString *m_aspectChoice_choices = NULL;
    m_aspectChoice = new wxChoice(this, ASPECT_CHOICE_ID, wxDefaultPosition, wxDefaultSize, 0, m_aspectChoice_choices, 0);
    const wxString m_interlacedChoice_choices[] = {
        _("progressive"),
        _("interlaced")
    };
    m_interlacedChoice = new wxChoice(this, INTERLACED_CHOICE_ID, wxDefaultPosition, wxDefaultSize, 2, m_interlacedChoice_choices, 0);
    const wxString m_ffChoice_choices[] = {
        _("auto"),
        _("BFF"),
        _("TFF")
    };
    m_ffChoice = new wxChoice(this, FF_CHOICE_ID, wxDefaultPosition, wxDefaultSize, 3, m_ffChoice_choices, 0);
    m_keepAspectCtrl = new wxCheckBox(this, KEEP_ASPECT_CB_ID, _("Keep Aspect Ratio"));
    m_padTop = new wxSpinCtrl(this, BORDER_UP_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_padLeft = new wxSpinCtrl(this, BORDER_LEFT_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_padRight = new wxSpinCtrl(this, BORDER_RIGHT_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_padBottom = new wxSpinCtrl(this, BORDER_DOWN_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_cropTop = new wxSpinCtrl(this, CROP_UP_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_cropLeft = new wxSpinCtrl(this, CROP_LEFT_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_cropRight = new wxSpinCtrl(this, CROP_RIGHT_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_cropBottom = new wxSpinCtrl(this, CROP_DOWN_CTRL_ID, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_fadeInLabel = new wxStaticText(this, wxID_ANY, _("Fade-In:"));
    m_fadeInCtrl = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_fadeInLabel2 = new wxStaticText(this, wxID_ANY, _("sec"));
    m_fadeOutLabel = new wxStaticText(this, wxID_ANY, _("Fade-Out:"));
    m_fadeOutCtrl = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999);
    m_fadeOutLabel2 = new wxStaticText(this, wxID_ANY, _("sec"));
    m_filtersLabel = new wxStaticText(this, wxID_ANY, _("Filters:"));
    m_filtersCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
    m_mediaCtrl = new MediaCtrlFF(this, wxID_ANY);
    m_slider = new wxSlider(this, SLIDER_ID, 0, 0, 10, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL|wxSL_TOP);
    m_timeLabel = new wxStaticText(this, wxID_ANY, _("Time:"));
    m_timeCtrl = new wxTextCtrl(this, TIME_CTRL_ID, wxEmptyString);
    m_timeSpinBt = new wxSpinButton(this, TIME_SPIN_BT_ID, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS);
    m_startLabel = new wxStaticText(this, wxID_ANY, _("Start:"));
    m_startCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
    m_startBt = new wxBitmapButton(this, START_BT_ID, wxNullBitmap);
    m_endLabel = new wxStaticText(this, wxID_ANY, _("End:"));
    m_endCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
    m_endBt = new wxBitmapButton(this, END_BT_ID, wxNullBitmap);
    m_okBt = new wxButton(this, wxID_OK, _("OK"));
    m_cancelBt = new wxButton(this, wxID_CANCEL, _("Cancel"));

    set_properties();
    do_layout();
    // end wxGlade
    
    wxCommandEvent evt;
    OnChangeFormat(evt);
    m_dstChoice->SetFocus();
}


void VideoPropDlg::set_properties() {
    // begin wxGlade: VideoPropDlg::set_properties
    SetTitle(_("Video properties"));
    m_interlacedChoice->SetSelection(0);
    m_ffChoice->SetSelection(0);
    m_padTop->SetMinSize(wxSize(58, -1));
    m_padLeft->SetMinSize(wxSize(58, -1));
    m_padRight->SetMinSize(wxSize(58, -1));
    m_padBottom->SetMinSize(wxSize(58, -1));
    m_cropTop->SetMinSize(wxSize(58, -1));
    m_cropLeft->SetMinSize(wxSize(58, -1));
    m_cropRight->SetMinSize(wxSize(58, -1));
    m_cropBottom->SetMinSize(wxSize(58, -1));
    m_mediaCtrl->SetMinSize(wxSize(300, 200));
    m_mediaCtrl->SetWindowStyle(wxBORDER_NONE);
    m_timeSpinBt->SetMinSize(wxSize(16, -1));
    m_startBt->SetBitmapLabel(wxArtProvider::GetBitmap(wxART_CUT, wxART_BUTTON));
    m_startBt->SetSize(m_startBt->GetBestSize());
    m_endBt->SetBitmapLabel(wxArtProvider::GetBitmap(wxART_CUT, wxART_BUTTON));
    m_endBt->SetSize(m_endBt->GetBestSize());
    m_okBt->SetDefault();
    // end wxGlade
    
    int x = 0;
	m_timeCtrl->GetTextExtent(wxT("00:00:00.000"), &x, NULL);
	m_timeCtrl->SetMinSize(wxSize(x + 10, -1));
	m_startCtrl->SetMinSize(wxSize(x + 10, -1));
	m_endCtrl->SetMinSize(wxSize(x + 10, -1));
    
    m_fileNameText->SetLabel(m_vob->GetFilenameDisplay());
    // duration
	wxString s = wxT("N/A");
	if (m_vob->GetDuration()>0) {
		int secs = (int) m_vob->GetDuration();
		int mins = secs / 60;
		secs %= 60;
		int hours = mins / 60;
		mins %= 60;
		s = wxString::Format(wxT("%02d:%02d:%02d"), hours, mins, secs);
	}
    m_durText->SetLabel(s);
    m_srcText->SetLabel(m_stream->GetSourceFormat());
    
    // format
    m_dstChoice->Append(DVD::GetVideoFormatLabels(true));
    m_dstChoice->SetSelection(m_stream->GetVideoFormat() - 1);
    m_aspectChoice->Append(DVD::GetAspectRatioLabels());
    m_aspectChoice->SetSelection(m_aspectRatio - 1);
    m_interlacedChoice->SetSelection(m_vob->GetInterlaced() ? 1 : 0);
    m_ffChoice->SetSelection(((int)m_vob->GetFirstField()) + 1);
    m_keepAspectCtrl->SetValue(m_vob->GetKeepAspectRatio());
    m_lastFormat = GetVideoFormat();
    
    // border
    m_padLeft->SetValue(m_vob->GetPad()[0]);
    m_padRight->SetValue(m_vob->GetPad()[1]);
    m_padTop->SetValue(m_vob->GetPad()[2]);
    m_padBottom->SetValue(m_vob->GetPad()[3]);
    
    // crop
    m_cropLeft->SetValue(m_vob->GetCrop()[0]);
    m_cropRight->SetValue(m_vob->GetCrop()[1]);
    m_cropTop->SetValue(m_vob->GetCrop()[2]);
    m_cropBottom->SetValue(m_vob->GetCrop()[3]);
    
    // fade-in / fade-out
    m_fadeInCtrl->SetValue(m_vob->GetFadeIn());
    m_fadeOutCtrl->SetValue(m_vob->GetFadeOut());
    m_filtersCtrl->SetValue(m_vob->GetVideoFilters());
    
    // start time
    int ms = lround(m_vob->GetStartTime() * 1000);
    ms = ms % 1000;
	long t = lround(m_vob->GetStartTime());
	m_startCtrl->SetValue(wxString::Format(wxT("%d:%02d:%02d.%03d"), t/3600, (t/60)%60, t%60, ms));
	
	// end time
	if (m_vob->GetRecordingTime() > 0) {
		ms = lround((m_vob->GetStartTime() + m_vob->GetRecordingTime()) * 1000);
		ms = ms % 1000;
		t = lround(m_vob->GetStartTime() + m_vob->GetRecordingTime());
		m_endCtrl->SetValue(wxString::Format(wxT("%d:%02d:%02d.%03d"), t/3600, (t/60) % 60, t%60, ms));
	}
}

void VideoPropDlg::do_layout() {
    // begin wxGlade: VideoPropDlg::do_layout
    wxBoxSizer* mainVSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* mainHSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* mediaSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* timeSizer = new wxBoxSizer(wxHORIZONTAL);
    wxFlexGridSizer* propSizer = new wxFlexGridSizer(2, 4, 2);
    wxBoxSizer* fadeOutSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* fadeInSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* propSizer2 = new wxBoxSizer(wxHORIZONTAL);
    wxStaticBoxSizer* m_cropBox = new wxStaticBoxSizer(m_cropBox_staticbox, wxHORIZONTAL);
    wxFlexGridSizer* cropSizer = new wxFlexGridSizer(3, 3, 4, 4);
    wxStaticBoxSizer* m_padBox = new wxStaticBoxSizer(m_padBox_staticbox, wxHORIZONTAL);
    wxFlexGridSizer* padSizer = new wxFlexGridSizer(3, 3, 4, 4);
    wxBoxSizer* dstSizer = new wxBoxSizer(wxHORIZONTAL);
    propSizer->Add(m_fileNameLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    propSizer->Add(m_fileNameText, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
    propSizer->Add(m_durLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    propSizer->Add(m_durText, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
    propSizer->Add(m_srcLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    propSizer->Add(m_srcText, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
    propSizer->Add(m_dstLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    dstSizer->Add(m_dstChoice, 0, wxALIGN_CENTER_VERTICAL, 0);
    dstSizer->Add(m_aspectChoice, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 6);
    dstSizer->Add(m_interlacedChoice, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 6);
    dstSizer->Add(m_ffChoice, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 6);
    propSizer->Add(dstSizer, 1, wxEXPAND, 0);
    propSizer->Add(20, 8, 0, wxEXPAND, 0);
    propSizer->Add(m_keepAspectCtrl, 0, 0, 0);
    propSizer->Add(20, 20, 0, wxEXPAND, 0);
    padSizer->Add(8, 8, 0, 0, 0);
    padSizer->Add(m_padTop, 0, 0, 0);
    padSizer->Add(8, 8, 0, 0, 0);
    padSizer->Add(m_padLeft, 0, 0, 0);
    padSizer->Add(8, 8, 0, 0, 0);
    padSizer->Add(m_padRight, 0, 0, 0);
    padSizer->Add(8, 8, 0, 0, 0);
    padSizer->Add(m_padBottom, 0, 0, 0);
    padSizer->Add(8, 8, 0, 0, 0);
    m_padBox->Add(padSizer, 1, wxALL, 4);
    propSizer2->Add(m_padBox, 0, wxRIGHT|wxEXPAND, 6);
    cropSizer->Add(8, 8, 0, 0, 0);
    cropSizer->Add(m_cropTop, 0, 0, 0);
    cropSizer->Add(8, 8, 0, 0, 0);
    cropSizer->Add(m_cropLeft, 0, 0, 0);
    cropSizer->Add(8, 8, 0, 0, 0);
    cropSizer->Add(m_cropRight, 0, 0, 0);
    cropSizer->Add(8, 8, 0, 0, 0);
    cropSizer->Add(m_cropBottom, 0, 0, 0);
    cropSizer->Add(8, 8, 0, 0, 0);
    m_cropBox->Add(cropSizer, 1, wxALL, 4);
    propSizer2->Add(m_cropBox, 0, wxEXPAND, 0);
    propSizer2->Add(2, 2, 1, wxEXPAND, 0);
    propSizer->Add(propSizer2, 1, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 6);
    propSizer->Add(m_fadeInLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    fadeInSizer->Add(m_fadeInCtrl, 0, wxALIGN_CENTER_VERTICAL, 0);
    fadeInSizer->Add(m_fadeInLabel2, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
    propSizer->Add(fadeInSizer, 1, wxEXPAND, 0);
    propSizer->Add(m_fadeOutLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    fadeOutSizer->Add(m_fadeOutCtrl, 0, wxALIGN_CENTER_VERTICAL, 0);
    fadeOutSizer->Add(m_fadeOutLabel2, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
    propSizer->Add(fadeOutSizer, 1, wxEXPAND, 0);
    propSizer->Add(m_filtersLabel, 0, 0, 0);
    propSizer->Add(m_filtersCtrl, 1, wxEXPAND, 0);
    propSizer->Add(20, 4, 0, wxEXPAND, 0);
    propSizer->Add(20, 4, 0, wxEXPAND, 0);
    propSizer->Add(4, 4, 0, 0, 0);
    propSizer->Add(4, 4, 0, 0, 0);
    propSizer->AddGrowableRow(9);
    propSizer->AddGrowableCol(1);
    mainHSizer->Add(propSizer, 0, wxALL|wxEXPAND, 10);
    mediaSizer->Add(m_mediaCtrl, 1, wxEXPAND, 0);
    mediaSizer->Add(m_slider, 0, wxEXPAND, 0);
    timeSizer->Add(m_timeLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 2);
    timeSizer->Add(m_timeCtrl, 0, wxEXPAND, 0);
    timeSizer->Add(m_timeSpinBt, 0, wxRIGHT|wxEXPAND|wxALIGN_CENTER_VERTICAL, 4);
    timeSizer->Add(m_startLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 2);
    timeSizer->Add(m_startCtrl, 0, wxRIGHT|wxEXPAND, 2);
    timeSizer->Add(m_startBt, 0, wxRIGHT, 4);
    timeSizer->Add(m_endLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 2);
    timeSizer->Add(m_endCtrl, 0, wxRIGHT|wxEXPAND, 2);
    timeSizer->Add(m_endBt, 0, 0, 0);
    mediaSizer->Add(timeSizer, 0, wxEXPAND, 0);
    mainHSizer->Add(mediaSizer, 1, wxALL|wxEXPAND, 4);
    mainVSizer->Add(mainHSizer, 1, wxEXPAND, 0);
    buttonSizer->Add(10, 10, 1, wxEXPAND, 0);
    buttonSizer->Add(m_okBt, 0, 0, 0);
    buttonSizer->Add(8, 8, 0, 0, 0);
    buttonSizer->Add(m_cancelBt, 0, 0, 0);
    buttonSizer->Add(10, 10, 1, wxEXPAND, 0);
    mainVSizer->Add(buttonSizer, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 4);
    SetSizer(mainVSizer);
    mainVSizer->Fit(this);
    Layout();
    Centre();
    // end wxGlade
}

double TimeToDouble(wxString timeStr) {
	wxRegEx re(wxT("^(([[:digit:]]+:)?([[:digit:]]?[[:digit:]]):)?([[:digit:]]?[[:digit:]])(\\.[[:digit:]]+)?$"));
	if (!re.Matches(timeStr))
		return -1;
	double result = 0;
	long lval;
	wxString val = re.GetMatch(timeStr, 2).BeforeFirst(wxT(':'));
	if (val.ToLong(&lval))
		result += lval*3600;
	val = re.GetMatch(timeStr, 3).BeforeFirst(wxT(':'));
	if (val.ToLong(&lval))
		result += lval*60;
	val = re.GetMatch(timeStr, 4);
	if (val.ToLong(&lval))
		result += lval;
	val = re.GetMatch(timeStr, 5).Mid(1);
	if (val.ToLong(&lval) && val.length() <= 3)
		result += ((double) lval) / (val.length() == 1 ? 10 : val.length() == 2 ? 100 : 1000);
	return result;
}

VideoFormat VideoPropDlg::GetVideoFormat() {
	return (VideoFormat) (m_dstChoice->GetSelection() + 1);
}

AspectRatio VideoPropDlg::GetAspectRatio() {
	return (AspectRatio) (m_aspectChoice->GetSelection() + 1);
}

vector<int> VideoPropDlg::GetPad() {
	int a[4] = { m_padLeft->GetValue(), m_padRight->GetValue(), m_padTop->GetValue(), m_padBottom->GetValue() };
	return vector<int>(a, a + sizeof(a)/sizeof(*a));
}

vector<int> VideoPropDlg::GetCrop() {
	int a[4] = { m_cropLeft->GetValue(), m_cropRight->GetValue(), m_cropTop->GetValue(), m_cropBottom->GetValue() };
	return vector<int>(a, a + sizeof(a)/sizeof(*a));
}

/**
 * Displays dialog
 */
int VideoPropDlg::ShowModal() {
	m_mediaCtrl->Load(m_vob->GetFilename());
	m_slider->SetMax(m_mediaCtrl->Length()/1000);
	m_timeSpinBt->SetMax(m_mediaCtrl->Length()/1000);
	wxScrollEvent scrlEvt;
	OnSliderScroll(scrlEvt);
	int res = wxDialog::ShowModal();
	if (res == wxID_OK) {
		m_stream->SetDestinationFormat(GetVideoFormat());
		m_vob->GetPad() = GetPad();
		m_vob->GetCrop() = GetCrop();
		m_vob->SetInterlaced(m_interlacedChoice->GetSelection() == 1);
		m_vob->SetFirstField((FirstField) (m_ffChoice->GetSelection() - 1));
		m_vob->SetKeepAspectRatio(m_keepAspectCtrl->GetValue());
		m_vob->SetFadeIn(m_fadeInCtrl->GetValue());
		m_vob->SetFadeOut(m_fadeOutCtrl->GetValue());
		m_vob->SetVideoFilters(m_filtersCtrl->GetValue());
		double time = TimeToDouble(m_startCtrl->GetValue());
		m_vob->SetStartTime(time >= 0 ? time : 0);
		time = TimeToDouble(m_endCtrl->GetValue());
		m_vob->SetRecordingTime(time > m_vob->GetStartTime() ? time - m_vob->GetStartTime() : -1);
	}
	return res;
}

void VideoPropDlg::UpdatePad() {
	if (m_keepAspectCtrl->GetValue()) {
		int padx = 0;
		int pady = 0;
		if (m_vob->CalcPad(padx, pady, GetVideoFormat(), GetAspectRatio(), GetCrop())) {
			m_padLeft->SetValue(padx);
			m_padRight->SetValue(padx);
			m_padTop->SetValue(pady);
			m_padBottom->SetValue(pady);
		}
	}
	// update preview
	m_mediaCtrl->SetVideoFormat(GetVideoFormat(), GetAspectRatio(), GetPad(), GetCrop());
}

void VideoPropDlg::SeekVideo(long pos, bool updateTimeCtrl) {
	m_slider->SetValue(lround(pos / 1000));
	m_timeSpinBt->SetValue(lround(pos / 1000));
	m_mediaCtrl->Seek((wxFileOffset) pos);
	if (updateTimeCtrl)
		m_timeCtrl->ChangeValue(Time2String(pos, true));
}

// wxGlade: add VideoPropDlg event handlers
void VideoPropDlg::OnChangeFormat(wxCommandEvent &event) {
	// update keepAspect, border and crop controls
	if (GetVideoFormat() == vfCOPY) {
		m_interlacedChoice->SetSelection(0);
		m_keepAspectCtrl->SetValue(false);
		m_padLeft->SetValue(0);
		m_padRight->SetValue(0);
		m_padTop->SetValue(0);
		m_padBottom->SetValue(0);
		m_cropLeft->SetValue(0);
		m_cropRight->SetValue(0);
		m_cropTop->SetValue(0);
		m_cropBottom->SetValue(0);
	} else if (m_lastFormat == vfCOPY)
		m_keepAspectCtrl->SetValue(true);
	m_lastFormat = GetVideoFormat();
	
	// enable/disable controls
	bool enable = m_dstChoice->GetSelection() > 0;
	bool enablePad = enable && !m_keepAspectCtrl->GetValue();
	m_interlacedChoice->Enable(enable);
	m_keepAspectCtrl->Enable(enable);
	m_cropBox_staticbox->Enable(enable);
	m_padBox_staticbox->Enable(enablePad);
	m_padLeft->Enable(enablePad);
	m_padRight->Enable(enablePad);
	m_padTop->Enable(enablePad);
	m_padBottom->Enable(enablePad);
	m_cropLeft->Enable(enable);
	m_cropRight->Enable(enable);
	m_cropTop->Enable(enable);
	m_cropBottom->Enable(enable);
	m_fadeInCtrl->Enable(enable);
	m_fadeOutCtrl->Enable(enable);
	m_filtersCtrl->Enable(enable);
	wxCommandEvent evt;
	OnInterlaced(evt);
	UpdatePad();
}

void VideoPropDlg::OnInterlaced(wxCommandEvent &event) {
	m_ffChoice->Enable(m_interlacedChoice->GetSelection() == 1);
	if (m_interlacedChoice->GetSelection() == 0)
		m_ffChoice->SetSelection(0);
}

void VideoPropDlg::OnChangeAspect(wxCommandEvent &event) {
	UpdatePad();
}

void VideoPropDlg::OnChangeKeepAspect(wxCommandEvent &event) {
	bool enable = !m_keepAspectCtrl->GetValue();
	m_padBox_staticbox->Enable(enable);
	m_padLeft->Enable(enable);
	m_padRight->Enable(enable);
	m_padTop->Enable(enable);
	m_padBottom->Enable(enable);
	if (enable) {
		m_padLeft->SetValue(0);
		m_padRight->SetValue(0);
		m_padTop->SetValue(0);
		m_padBottom->SetValue(0);
	}
	UpdatePad();
}

void VideoPropDlg::OnChangeBorder(wxSpinEvent &event) {
	// update preview
	m_mediaCtrl->SetVideoFormat(GetVideoFormat(), GetAspectRatio(), GetPad(), GetCrop());
}

void VideoPropDlg::OnChangeCrop(wxSpinEvent &event) {
	UpdatePad();
}

void VideoPropDlg::OnSliderScroll(wxScrollEvent &event) {
	SeekVideo(((long)m_slider->GetValue())*1000);
}

void VideoPropDlg::OnChangeTime(wxCommandEvent &event) {
	wxRegEx re(wxT("^(([[:digit:]]+:)?[[:digit:]][[:digit:]]?:)?[[:digit:]][[:digit:]]?(\\.[[:digit:]]+)?$"));
	if (re.Matches(m_timeCtrl->GetValue()))
		SeekVideo(String2Time(m_timeCtrl->GetValue()), false);
}

void VideoPropDlg::OnTimeSpin(wxSpinEvent &event) {
	SeekVideo(((long)m_timeSpinBt->GetValue())*1000);
}

void VideoPropDlg::OnStartBt(wxCommandEvent &event) {
	int ms = m_slider->GetValue() != 0 ? m_mediaCtrl->Tell() % 1000 : 0;
	int t = m_mediaCtrl->Tell() / 1000;
	m_startCtrl->SetValue(wxString::Format(wxT("%d:%02d:%02d.%03d"), t/3600, (t/60) % 60, t%60, ms));
}

void VideoPropDlg::OnEndBt(wxCommandEvent &event) {
	if (m_slider->GetValue() < m_slider->GetMax()) {
		int ms = m_mediaCtrl->Tell() % 1000;
		int t = m_mediaCtrl->Tell() / 1000;
		m_endCtrl->SetValue(wxString::Format(wxT("%d:%02d:%02d.%03d"), t/3600, (t/60) % 60, t%60, ms));
	} else
		m_endCtrl->SetValue(wxT(""));
}

void VideoPropDlg::OnOkBt(wxCommandEvent &event) {
	if (m_startCtrl->GetValue().length() > 0 && TimeToDouble(m_startCtrl->GetValue()) == -1) {
		wxLogError(_("Invalid time") + wxString(wxT(": ")) + m_startCtrl->GetValue());
		event.Skip();
		return;
	}
	if (m_endCtrl->GetValue().length() > 0 && TimeToDouble(m_endCtrl->GetValue()) == -1) {
		wxLogError(_("Invalid time") + wxString(wxT(": ")) + m_startCtrl->GetValue());
		event.Skip();
		return;
	}
	this->EndModal(wxID_OK);
}
