bool mmg_app::OnInit() { #ifdef __WXMAC__ ProcessSerialNumber PSN; GetCurrentProcess(&PSN); TransformProcessType(&PSN, kProcessTransformToForegroundApplication); #endif wxImage::AddHandler(new wxPNGHandler); mtx_common_init("mmg"); wxConfigBase *cfg; uint32_t i; wxString k, v; int index; prepare_mmg_data_folder(); #if defined(SYS_WINDOWS) cfg = new wxConfig(wxT("mkvmergeGUI")); #else cfg = new wxFileConfig(wxT("mkvmergeGUI"), wxEmptyString, get_config_file_name()); #endif cfg->SetExpandEnvVars(false); wxConfigBase::Set(cfg); init_ui_locale(); cfg->SetPath(wxT("/GUI")); cfg->Read(wxT("last_directory"), &last_open_dir, wxEmptyString); for (i = 0; i < 4; i++) { k.Printf(wxT("last_settings %u"), i); if (cfg->Read(k, &v) && wxFile::Exists(v)) last_settings.push_back(v); k.Printf(wxT("last_chapters %u"), i); if (cfg->Read(k, &v) && wxFile::Exists(v)) last_chapters.push_back(v); } cfg->SetPath(wxT("/chapter_editor")); cfg->Read(wxT("default_language"), &k, wxT("und")); g_default_chapter_language = wxMB(k); index = map_to_iso639_2_code(g_default_chapter_language.c_str()); if (-1 == index) g_default_chapter_language = "und"; else g_default_chapter_language = iso639_languages[index].iso639_2_code; if (cfg->Read(wxT("default_country"), &k) && (0 < k.length())) g_default_chapter_country = wxMB(k); if (!is_valid_cctld(g_default_chapter_country.c_str())) g_default_chapter_country = ""; app = this; mdlg = new mmg_dialog(); mdlg->Show(true); handle_command_line_arguments(); return true; }
void mmg_app::init_ui_locale() { std::string locale; #if defined(HAVE_LIBINTL_H) static bool s_first_init = true; wxString w_locale; translation_c::initialize_available_translations(); wxConfigBase *cfg = wxConfigBase::Get(); cfg->SetPath(wxT("/GUI")); if (cfg->Read(wxT("ui_locale"), &w_locale)) { locale = wxMB(w_locale); if (-1 == translation_c::look_up_translation(locale)) locale = ""; } if (locale.empty()) { locale = translation_c::get_default_ui_locale(); if (-1 == translation_c::look_up_translation(locale)) locale = ""; } m_ui_locale = locale; if (s_first_init) { std::string installation_path = get_installation_path(); if (!installation_path.empty()) wxLocale::AddCatalogLookupPathPrefix(wxU(installation_path + "/locale")); } const wxLanguageInfo *lang_info = wxLocale::FindLanguageInfo(wxU(m_ui_locale)); if (s_first_init) { if (lang_info && m_locale.Init(lang_info->Language)) { m_locale.AddCatalog(wxU("wxstd")); #ifdef SYS_WINDOWS m_locale.AddCatalog(wxU("wxmsw")); #endif // SYS_WINDOWS } delete wxLog::SetActiveTarget(nullptr); s_first_init = false; } #endif // HAVE_LIBINTL_H init_locales(locale); }
void tab_attachments::add_attachment(const wxString &file_name) { mmg_attachment_cptr attch = mmg_attachment_cptr(new mmg_attachment_t); attch->file_name = file_name; wxString name = file_name.AfterLast(wxT(PSEP)); wxString ext = name.AfterLast(wxT('.')); name += wxString(wxT(" (")) + file_name.BeforeLast(wxT(PSEP)) + wxT(")"); lb_attachments->Append(name); if (ext.Length() > 0) attch->mime_type = wxU(guess_mime_type(wxMB(file_name), true)); attch->style = 0; attch->stored_name = derive_stored_name_from_file_name(attch->file_name); attachments.push_back(attch); }
void mmg_app::handle_command_line_arguments() { if (1 >= app->argc) return; std::vector<std::string> args; size_t i; for (i = 1; static_cast<size_t>(app->argc) > i; ++i) args.push_back(wxMB(wxString(app->argv[i]))); handle_common_cli_args(args, ""); if (args.empty()) return; std::vector<wxString> wargs; for (i = 0; args.size() > i; ++i) wargs.push_back(wxU(args[i])); if (wargs[0] == wxT("--edit-headers")) { if (wargs.size() == 1) wxMessageBox(Z("Missing file name after for the option '--edit-headers'."), Z("Missing file name"), wxOK | wxCENTER | wxICON_ERROR); else mdlg->create_header_editor_window(wargs[1]); return; } for (auto &file : wargs) if (!wxFileExists(file) || wxDirExists(file)) wxMessageBox(wxString::Format(Z("The file '%s' does not exist."), file.c_str()), Z("Error loading settings"), wxOK | wxCENTER | wxICON_ERROR); else { #ifdef SYS_WINDOWS if ((file.Length() > 3) && (file.c_str()[1] != wxT(':')) && (file.c_str()[0] != wxT('\\'))) file = wxGetCwd() + wxT("\\") + file; #else if ((file.Length() > 0) && (file.c_str()[0] != wxT('/'))) file = wxGetCwd() + wxT("/") + file; #endif if (wxFileName(file).GetExt() == wxU("mmg")) mdlg->load(file); else mdlg->input_page->add_file(file, false); } }
void mmg_app::prepare_mmg_data_folder() { // The 'jobs' folder is part of the application data // folder. Therefore both directories will be creatd. // 'prepare_path' treats the last part of the path as a file name; // therefore append a dummy file name so that all directory parts // will be created. mm_file_io_c::prepare_path(wxMB(get_jobs_folder() + wxT("/dummy"))); #if !defined(SYS_WINDOWS) // Migrate the config file from its old location ~/.mkvmergeGUI to // the new location ~/.mkvtoolnix/config wxString old_config_name; wxGetEnv(wxT("HOME"), &old_config_name); old_config_name += wxT("/.mkvmergeGUI"); if (wxFileExists(old_config_name)) wxRenameFile(old_config_name, get_config_file_name()); #endif }
void mmg_options_t::init_popular_languages(const wxString &list) { size_t i; popular_languages.clear(); if (!list.IsEmpty()) { std::vector<wxString> codes = split(list, wxU(" ")); for (i = 0; codes.size() > i; ++i) if (is_valid_iso639_2_code(wxMB(codes[i]))) popular_languages.Add(codes[i]); } if (popular_languages.IsEmpty()) { std::map<std::string, bool> codes_found; for (auto lang : g_iso639_languages) if (!codes_found[lang.iso639_2_code] && is_popular_language_code(lang.iso639_2_code)) { popular_languages.Add(wxU(lang.iso639_2_code)); codes_found[lang.iso639_2_code] = true; } } popular_languages.Sort(); }
bool header_editor_frame_c::open_file(wxFileName file_name) { if (!kax_analyzer_c::probe(wxMB(file_name.GetFullPath()))) { wxMessageBox(Z("The file you tried to open is not a Matroska file."), Z("Wrong file selected"), wxOK | wxCENTER | wxICON_ERROR); return false; } m_e_segment_info.clear(); m_e_tracks.clear(); m_analyzer = wx_kax_analyzer_cptr(new wx_kax_analyzer_c(this, wxMB(file_name.GetFullPath()))); if (!m_analyzer->process(kax_analyzer_c::parse_mode_fast)) { wxMessageBox(Z("This file could not be opened or parsed."), Z("File parsing failed"), wxOK | wxCENTER | wxICON_ERROR); m_analyzer.clear(); return false; } m_file_name = file_name; m_file_name.GetTimes(NULL, &m_file_mtime, NULL); set_window_title(); m_ignore_tree_selection_changes = true; enable_menu_entries(); m_bs_main->Hide(m_tc_tree); size_t i; for (i = 0; m_pages.size() > i; ++i) if (m_pages[i]->IsShown()) m_pages[i]->Hide(); m_tc_tree->DeleteChildren(m_root_id); m_bs_page->Clear(); m_pages.clear(); m_top_level_pages.clear(); for (i = 0; m_analyzer->m_data.size() > i; ++i) { kax_analyzer_data_c *data = m_analyzer->m_data[i].get_object(); if (data->m_id == KaxInfo::ClassInfos.GlobalId) { handle_segment_info(data); break; } } for (i = 0; m_analyzer->m_data.size() > i; ++i) { kax_analyzer_data_c *data = m_analyzer->m_data[i].get_object(); if (data->m_id == KaxTracks::ClassInfos.GlobalId) { handle_tracks(data); break; } } m_analyzer->close_file(); m_bs_main->Show(m_tc_tree); m_bs_main->Layout(); last_open_dir = file_name.GetPath(); m_ignore_tree_selection_changes = false; return true; }
mux_dialog::mux_dialog(wxWindow *parent): wxDialog(parent, -1, Z("mkvmerge is running"), wxDefaultPosition, #ifdef SYS_WINDOWS wxSize(700, 560), #else wxSize(700, 520), #endif wxDEFAULT_FRAME_STYLE) #if defined(SYS_WINDOWS) , pid(0) , m_taskbar_progress(NULL) , m_abort_button_changed(false) #endif // SYS_WINDOWS , m_exit_code(0) , m_progress(0) { char c; std::string arg_utf8, line; long value; wxString wx_line, tmp; wxInputStream *out; wxFile *opt_file; uint32_t i; wxArrayString *arg_list; wxBoxSizer *siz_all, *siz_buttons, *siz_line; wxStaticBoxSizer *siz_status, *siz_output; m_window_disabler = new wxWindowDisabler(this); c = 0; siz_status = new wxStaticBoxSizer(new wxStaticBox(this, -1, Z("Status and progress")), wxVERTICAL); st_label = new wxStaticText(this, -1, wxEmptyString); st_remaining_time_label = new wxStaticText(this, -1, Z("Remaining time:")); st_remaining_time = new wxStaticText(this, -1, Z("is being estimated")); siz_line = new wxBoxSizer(wxHORIZONTAL); siz_line->Add(st_label); siz_line->AddSpacer(5); siz_line->Add(st_remaining_time_label); siz_line->AddSpacer(5); siz_line->Add(st_remaining_time); siz_status->Add(siz_line, 0, wxGROW | wxALIGN_LEFT | wxALL, 5); g_progress = new wxGauge(this, -1, 100, wxDefaultPosition, wxSize(250, 15)); siz_status->Add(g_progress, 1, wxALL | wxGROW, 5); siz_output = new wxStaticBoxSizer(new wxStaticBox(this, -1, Z("Output")), wxVERTICAL); siz_output->Add(new wxStaticText(this, -1, Z("mkvmerge output:")), 0, wxALIGN_LEFT | wxALL, 5); tc_output = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_BESTWRAP | wxTE_MULTILINE); siz_output->Add(tc_output, 2, wxGROW | wxALL, 5); siz_output->Add(new wxStaticText(this, -1, Z("Warnings:")), 0, wxALIGN_LEFT | wxALL, 5); tc_warnings = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_BESTWRAP | wxTE_MULTILINE); siz_output->Add(tc_warnings, 1, wxGROW | wxALL, 5); siz_output->Add(new wxStaticText(this, -1, Z("Errors:")), 0, wxALIGN_LEFT | wxALL, 5); tc_errors = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_BESTWRAP | wxTE_MULTILINE); siz_output->Add(tc_errors, 1, wxGROW | wxALL, 5); siz_buttons = new wxBoxSizer(wxHORIZONTAL); siz_buttons->AddStretchSpacer(); b_ok = new wxButton(this, ID_B_MUX_OK, Z("Ok")); b_ok->Enable(false); siz_buttons->Add(b_ok, 0, wxGROW); siz_buttons->AddStretchSpacer(); b_abort = new wxButton(this, ID_B_MUX_ABORT, Z("Abort")); siz_buttons->Add(b_abort, 0, wxGROW); siz_buttons->AddStretchSpacer(); b_save_log = new wxButton(this, ID_B_MUX_SAVELOG, Z("Save log")); siz_buttons->Add(b_save_log, 0, wxGROW); siz_buttons->AddStretchSpacer(); siz_all = new wxBoxSizer(wxVERTICAL); siz_all->Add(siz_status, 0, wxGROW | wxALL, 5); siz_all->Add(siz_output, 1, wxGROW | wxALL, 5); siz_all->Add(siz_buttons, 0, wxGROW | wxALL, 10); SetSizer(siz_all); update_window(Z("Muxing in progress.")); Show(true); process = new mux_process(this); opt_file_name.Printf(wxT("%smmg-mkvmerge-options-%d-%d"), get_temp_dir().c_str(), (int)wxGetProcessId(), (int)wxGetUTCTime()); try { const unsigned char utf8_bom[3] = {0xef, 0xbb, 0xbf}; opt_file = new wxFile(opt_file_name, wxFile::write); opt_file->Write(utf8_bom, 3); } catch (...) { wxString error; error.Printf(Z("Could not create a temporary file for mkvmerge's command line option called '%s' (error code %d, %s)."), opt_file_name.c_str(), errno, wxUCS(strerror(errno))); wxMessageBox(error, Z("File creation failed"), wxOK | wxCENTER | wxICON_ERROR); throw 0; } arg_list = &static_cast<mmg_dialog *>(parent)->get_command_line_args(); for (i = 1; i < arg_list->Count(); i++) { if ((*arg_list)[i].Length() == 0) opt_file->Write(wxT("#EMPTY#")); else { arg_utf8 = escape(wxMB((*arg_list)[i])); opt_file->Write(arg_utf8.c_str(), arg_utf8.length()); } opt_file->Write(wxT("\n")); } delete opt_file; #if defined(SYS_WINDOWS) if (get_windows_version() >= WINDOWS_VERSION_7) { m_taskbar_progress = new taskbar_progress_c(mdlg); m_taskbar_progress->set_state(TBPF_NORMAL); m_taskbar_progress->set_value(0, 100); } #endif // SYS_WINDOWS m_start_time = get_current_time_millis(); m_next_remaining_time_update = m_start_time + 8000; wxString command_line = wxString::Format(wxT("\"%s\" \"@%s\""), (*arg_list)[0].c_str(), opt_file_name.c_str()); pid = wxExecute(command_line, wxEXEC_ASYNC, process); if (0 == pid) { wxLogError(wxT("Execution of '%s' failed."), command_line.c_str()); done(2); return; } out = process->GetInputStream(); line = ""; log = wxEmptyString; while (1) { while (app->Pending()) app->Dispatch(); if (!out->CanRead() && !out->Eof()) { wxMilliSleep(5); continue; } if (!out->Eof()) c = out->GetC(); else c = '\n'; if ((c == '\n') || (c == '\r') || out->Eof()) { wx_line = wxU(line); log += wx_line; if (c != '\r') log += wxT("\n"); if (wx_line.Find(Z("Warning:")) == 0) tc_warnings->AppendText(wx_line + wxT("\n")); else if (wx_line.Find(Z("Error:")) == 0) tc_errors->AppendText(wx_line + wxT("\n")); else if (wx_line.Find(Z("Progress")) == 0) { if (wx_line.Find(wxT("%")) != 0) { wx_line.Remove(wx_line.Find(wxT("%"))); tmp = wx_line.AfterLast(wxT(' ')); tmp.ToLong(&value); if ((value >= 0) && (value <= 100)) update_gauge(value); } } else if (wx_line.Length() > 0) tc_output->AppendText(wx_line + wxT("\n")); line = ""; update_remaining_time(); } else if ((unsigned char)c != 0xff) line += c; if (out->Eof()) break; } }
void job_run_dialog::start_next_job() { t_update->Stop(); ++current_job; if ((static_cast<int>(jobs_to_start.size()) <= current_job) || cb_abort_after_current->IsChecked() || abort) { if ( abort || ( cb_abort_after_current->IsChecked() && (current_job < static_cast<int>(jobs_to_start.size())))) add_to_log(wxString::Format(Z("Aborted processing on %s"), format_date_time(wxGetUTCTime()).c_str())); else add_to_log(wxString::Format(Z("Finished processing on %s"), format_date_time(wxGetUTCTime()).c_str())); b_abort->Enable(false); cb_abort_after_current->Enable(false); b_ok->Enable(true); b_ok->SetFocus(); SetTitle(Z("mkvmerge has finished")); st_remaining_time->SetLabel(wxT("---")); st_remaining_time_total->SetLabel(wxT("---")); #if defined(SYS_WINDOWS) if (m_taskbar_progress) m_taskbar_progress->set_state(TBPF_NOPROGRESS); #endif return; } m_start_time = mtx::sys::get_current_time_millis(); m_next_remaining_time_update = m_start_time + 8000; st_remaining_time->SetLabel(Z("is being estimated")); #if defined(SYS_WINDOWS) if (m_taskbar_progress) { m_taskbar_progress->set_state(TBPF_NORMAL); m_taskbar_progress->set_value(current_job * 100, jobs_to_start.size() * 100); } #endif int ndx = jobs_to_start[current_job]; st_jobs->SetLabel(wxString::Format(Z("Processing job %d/%d"), current_job + 1, (int)jobs_to_start.size())); st_current->SetLabel(wxString::Format(Z("Current job ID %d:"), jobs[ndx].id)); mdlg->load(wxString::Format(wxT("%s/%d.mmg"), app->get_jobs_folder().c_str(), jobs[ndx].id), true); opt_file_name = get_temp_settings_file_name(); wxFile *opt_file; try { opt_file = new wxFile(opt_file_name, wxFile::write); } catch (...) { jobs[ndx].log->Printf(Z("Could not create a temporary file for mkvmerge's command line option called '%s' (error code %d, %s)."), opt_file_name.c_str(), errno, wxUCS(strerror(errno))); jobs[ndx].status = JOBS_FAILED; mdlg->save_job_queue(); if (process) { delete process; process = nullptr; } start_next_job(); return; } static const unsigned char utf8_bom[3] = {0xef, 0xbb, 0xbf}; opt_file->Write(utf8_bom, 3); opt_file->Write(wxT("--gui-mode\n")); mdlg->update_command_line(); wxArrayString *arg_list = &mdlg->get_command_line_args(); size_t i; for (i = 1; i < arg_list->Count(); i++) { if ((*arg_list)[i].Length() == 0) opt_file->Write(wxT("#EMPTY#")); else { std::string arg_utf8 = escape(wxMB((*arg_list)[i])); opt_file->Write(arg_utf8.c_str(), arg_utf8.length()); } opt_file->Write(wxT("\n")); } delete opt_file; process = new wxProcess(this, 1); process->Redirect(); wxString command_line = wxString::Format(wxT("\"%s\" \"@%s\""), (*arg_list)[0].c_str(), opt_file_name.c_str()); pid = wxExecute(command_line, wxEXEC_ASYNC, process); if (0 == pid) { wxLogError(wxT("Execution of '%s' failed."), command_line.c_str()); return; } out = process->GetInputStream(); *jobs[ndx].log = wxEmptyString; jobs[ndx].started_on = wxGetUTCTime(); jobs[ndx].finished_on = -1; add_to_log(wxString::Format(Z("Starting job ID %d (%s) on %s"), jobs[ndx].id, jobs[ndx].description->c_str(), format_date_time(jobs[ndx].started_on).c_str())); t_update->Start(100); }