Last active
August 29, 2015 14:27
-
-
Save yumetodo/cc48d6543d9320a9fe6c to your computer and use it in GitHub Desktop.
x264guiExのrunbat.cppにあるrun_bat_file関数(line:43)をstd::stringとか使って書き換え、run_bat_file_cpp関数(line:262)を作った。ビルドテストなんてしてない。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <shlwapi.h> | |
#pragma comment(lib, "shlwapi.lib") | |
#include "auo.h" | |
#include "auo_version.h" | |
#include "auo_util.h" | |
#include "auo_conf.h" | |
#include "auo_settings.h" | |
#include "auo_system.h" | |
#include "auo_pipe.h" | |
#include "auo_encode.h" | |
#include "auo_error.h" | |
#include "auo_frm.h" | |
#include <string> | |
#include <fstream> | |
#include <algolizm> | |
#include <cctype> | |
#include <utility> | |
bool str_has_char(const std::string& str){ | |
return !str.empty() && std::none_of(str.begin(), str.end(), [](const char& a){ return isspace(a); }); | |
} | |
template<std::size_t N> bool str_has_char(char (&str_arr)[N]){ | |
return N && std::none_of(begin(str_arr), end(str_arr), [](const char& a){ return isspace(a); }); | |
} | |
template<typename T> void replace_all(std::basic_string<T>& str, const std::basic_string<T>& old_str, const std::basic_string<T>& new_str){ | |
for(size_t i = str.find_first_of(old_str); std::string::npos != i; i = str.find_first_of(old_str, i + new_str.length())){ | |
str.replace(i, old_str.length(), new_str); | |
} | |
} | |
std::string get_path_nx(const std::string& pathdpnx){ | |
return pathdpnx.substr(pathdpnx.find_last_of('\\', pathdpnx.length() - 2));//最終文字が'\'の時はその文字を無視 | |
} | |
std::string remove_last_backslash(const std::string& str){ | |
return str.substr(0, (str.last() == '\\') ? str.length() - 2 : std::string::npos); | |
} | |
std::string apply_appendix(std::string&& str, const char* appendix){ | |
const auto appendix_i = re.find_last_of('.'); | |
re.replace(appendix_i, re.length() - appendix_i, appendix); | |
return std::move(re); | |
} | |
std::string apply_appendix(const std::string& str, const char* appendix){ | |
auto re = str; | |
return apply_appendix(std::move(re), appendix); | |
} | |
std::string get_aud_filename(const std::string& filenx, const PRM_ENC& pe, size_t i_aud){ | |
auto re = std::string(pe.aud_temp_dir); | |
if(re.back() != '\\') re += '\\'; | |
re += filenx; | |
return re + filenx + pe.append.aud[i_aud]; | |
} | |
std::string get_muxout_filename(const std::string& filedpnx, const PRM_ENC& pe, const SYSTEM_DATA& sys_dat){ | |
static const char * const MUXOUT_APPENDIX = "_muxout"; | |
std::string o_ext = (pe.muxer_to_be_used >= 0) ? sys_dat.exstg->s_mux[pe.muxer_to_be_used].out_ext : ""; | |
const auto ext = (!o_ext.empty() && str_has_char(o_ext)) ? o_ext : filedpnx.substr(find_last_of('.') + 1); | |
return apply_appendix(filedpnx, MUXOUT_APPENDIX + ext); | |
} | |
auto get_fps(const CONF_GUIEX& conf, const OUTPUT_INFO& oip){ | |
int fps_rate = oip->rate; | |
int fps_scale = oip->scale; | |
#ifdef MSDK_SAMPLE_VERSION | |
if (conf->qsv.vpp.nDeinterlace == MFX_DEINTERLACE_IT) | |
fps_rate = (fps_rate * 4) / 5; | |
#endif | |
const int fps_gcd = get_gcd(fps_rate, fps_scale); | |
return std::make_pair(fps_rate / fps_gcd, fps_scale / fps_gcd) | |
} | |
struct point2d{ | |
int x, y; | |
point2d() : x(0), y(0) {} | |
point2d(int x_, int y_) : x(x_), y(y_) {} | |
point2d(const OUTPUT_INFO& oip) : x(oip.w), y(oip.h) {} | |
point2d(const point2d&) = default; | |
int diff(){ return (x < y) ? y - x : x - y ;} | |
bool tan_p_n() { return x * y > 0; }//positive or negative | |
void gcd() noexcept { | |
const auto g = get_gcd(x, y); | |
x /= g; | |
y /= g; | |
} | |
point2d operator= (int n) noexcept { | |
x = n; | |
y = n; | |
return *this; | |
} | |
operator INT2() const noexcept { | |
INT2 re; | |
re.x = x; re.y = y; | |
return re; | |
} | |
}; | |
bool operator< (const point2d& l, int r){ return l.x < r && l.y < r; } | |
bool operator> (const point2d& l, int r){ return l.x > r && l.y > r; } | |
bool operator< (const point2d& l, const point2d& r){ return l.x < r.x && l.y < r.y; } | |
bool operator> (const point2d& l, const point2d& r){ return l.x > r.x && l.y > r.y; } | |
point2d operator* (const std::pair<int, int>& l, const point2d& r){ return point2d(r.x * l.first, r.y * l.second); } | |
point2d operator* (int l, const point2d& r) const{ return point2d(r.x * l, r.y * l); } | |
point2d operator* (const OUTPUT_INFO& oip, const point2d& r){ return point2d(r.x * oip.x, r.y * oip.y); } | |
point2d operator* (const point2d& l, const std::pair<int, int>& r){ return point2d(l.x * r.first, l.y * r.second); } | |
point2d operator* (const point2d& l, int n) const{ return point2d(l.x * n, l.y * n); } | |
point2d operator* (const point2d& l, const OUTPUT_INFO& oip){ return point2d(l.x * oip.x, l.y * oip.y); } | |
point2d set_guiEx_auto_sar(const point2d& sar, const point2d& oip){ | |
point2d re; | |
if(oip > 0 && sar < 0){ | |
re = -1 * sar * oip; | |
if(re.diff() > -16 * sar) re.gcd(); | |
else re = 1; | |
} | |
return re; | |
} | |
static void set_guiEx_auto_sar(CONF_X264 *cx, int width, int height){ | |
&cx->sar = static_cast<INT2>(set_guiEx_auto_sar(point2d(&cx->sar.x, &cx->sar.y)), point2d(width, height)); | |
} | |
auto get_aspect_ratio(const CONF_GUIEX& conf, const OUTPUT_INFO& oip){ | |
point2d sar(conf->x264.sar.x, conf->x264.sar.y); | |
point2d dar; | |
if (sar.tan_p_n()) { | |
if (sar.x < 0) { | |
dar = -1 * sar; | |
sar = set_guiEx_auto_sar(sar, conf); | |
} else { | |
dar = sar * conf; | |
dar.gcd(); | |
} | |
} | |
if (!sar.tan_p_n()) sar = 1; | |
if (!dar.tan_p_n()) dar = 1; | |
return std::make_pair(sar, dar); | |
} | |
std::string GetFullPath(const char* path){ | |
if (FALSE == PathIsRelativeA(path)) return std::string(path); | |
char buf[MAX_PATH_LEN]; | |
_fullpath(buf, path, MAX_PATH_LEN); | |
return std::string(buf); | |
} | |
void cmd_replace(std::string& cmd, const PRM_ENC& pe, const SYSTEM_DATA& sys_dat, const CONF_GUIEX& conf, const OUTPUT_INFO& oip){ | |
//置換操作の実行 | |
const auto filedpnx = std::string(pe.temp_filename); | |
const auto filenx = get_path_nx(filedpnx); | |
const auto savedpnx = std:string(oip.savefile); | |
const auto savenx = get_path_nx(savedpnx); | |
replace_all(cmd, "%{vidpath}", filedpnx); | |
//%{audpath} | |
for(size_t i = 0; i < pe.aud_count; ++i) { | |
if(str_has_char(pe.append.aud[i])){ | |
std::string aud_key_tmp = "%{audpath"; | |
replace_all(cmd, ((i) ? aud_key_tmp + "}" : aud_key_tmp + i + "}"), get_aud_filename(filenx, pe, i)); | |
} | |
} | |
replace_all(cmd, "%{tmpdir}", remove_last_backslash(filenx)); | |
replace_all(cmd, "%{tmpfile}", filedpnx.substr(0, filedpnx.find_last_of('.'))); | |
replace_all(cmd, "%{tmpname}", filenx.substr(0, filedpnx.find_last_of('.'))); | |
replace_all(cmd, "%{savpath}", savedpnx); | |
replace_all(cmd, "%{savfile}", savedpnx.substr(0, filedpnx.find_last_of('.'))); | |
replace_all(cmd, "%{savname}", savenx.substr(0, savenx.find_last_of('.'))); | |
replace_all(cmd, "%{savdir}", remove_last_backslash(savenx)); | |
replace_all(cmd, "%{aviutldir}", remove_last_backslash(sys_dat.aviutl_dir)); | |
replace_all(cmd, "%{chpath}", apply_appendix(savedpnx, pe.append.chap)); | |
replace_all(cmd, "%{tcpath}", apply_appendix(filedpnx, pe.append.tc)); | |
replace_all(cmd, "%{muxout}", get_muxout_filename(filedpnx, pe, sys_dat)); | |
const auto fps_info = get_fps(conf, oip); | |
replace_all(cmd, "%{fps_rate}", std::to_string(fps_info.first)); | |
replace_all(cmd, "%{fps_rate_times_4}", std::to_string(fps_info.first * 4)); | |
replace_all(cmd, "%{fps_scale}", std::to_string(fps_info.second)); | |
const auto aspect_ratio = get_aspect_ratio(conf, oip); | |
replace_all(cmd, "%{sar_x}", std::to_string(aspect_ratio.first.x)); | |
replace_all(cmd, "%{par_x}", std::to_string(aspect_ratio.first.x)); | |
replace_all(cmd, "%{sar_y}", std::to_string(aspect_ratio.first.y)); | |
replace_all(cmd, "%{par_x}", std::to_string(aspect_ratio.first.y)); | |
replace_all(cmd, "%{dar_x}", std::to_string(aspect_ratio.second.x)); | |
replace_all(cmd, "%{dar_y}", std::to_string(aspect_ratio.second.x)); | |
replace_all(cmd, "%{x264path}", GetFullPath(sys_dat->exstg->s_x264.fullpath); | |
replace_all(cmd, "%{x264_10path}", GetFullPath(sys_dat->exstg->s_x264.fullpath_highbit); | |
replace_all(cmd, "%{audencpath}", GetFullPath(sys_dat->exstg->s_aud[conf->aud.encoder].fullpath); | |
replace_all(cmd, "%{mp4muxerpath}", GetFullPath(sys_dat->exstg->s_mux[MUXER_MP4].fullpath); | |
replace_all(cmd, "%{mkvmuxerpath}", GetFullPath(sys_dat->exstg->s_mux[MUXER_MKV].fullpath); | |
} | |
bool DirectoryExistsOrCreate(const std::string& dir){ | |
if (PathIsDirectoryA(dir.c_str())) return true; | |
return (PathIsDirectoryA(dir.substr(dir.find_last_of('\\', dir.length() - 2)).c_str()) && nullptr != CreateDirectoryA(dir.c_str(), nullptr)) | |
} | |
AUO_RESULT getLogFilePath(std::string& log_file_path, const PRM_ENC& pe, const SYSTEM_DATA& sys_dat, const CONF_GUIEX& conf, const OUTPUT_INFO& oip) { | |
AUO_RESULT ret = AUO_RESULT_SUCCESS; | |
guiEx_settings stg(TRUE); //ログウィンドウの保存先設定は最新のものを使用する | |
stg.load_log_win(); | |
switch (stg.s_log.auto_save_log_mode) { | |
case AUTO_SAVE_LOG_CUSTOM: | |
log_file_path = stg.s_log.auto_save_log_path; | |
cmd_replace(log_file_path, pe, sys_dat, conf, oip); | |
if (DirectoryExistsOrCreate(log_file_path.substr(log_file_path.find_last_of('\\', log_file_path.length() - 2))) break; | |
//存在しないpathでかつ新規作成できなかった場合 | |
ret = AUO_RESULT_WARNING; | |
//下へフォールスルー | |
case AUTO_SAVE_LOG_OUTPUT_DIR: | |
default: | |
log_file_path = apply_appendix(oip.savefile, "_log.txt"); | |
break; | |
} | |
return ret; | |
} | |
std::string get_chapter_apple(std::string& chap_file, const PRM_ENC& pe, const SYSTEM_DATA& sys_dat){ | |
if(chap_file.empty()) return std::string(""); | |
auto chap_apple = apply_appendix(get_path_nx(chap_file), pe.append.chap_apple); | |
for(auto& i_rep : sys_dat->exstg->fn_rep) replace_all(chap_apple, i_rep.from, i_rep.to); | |
return std::move(chap_apple); | |
} | |
void bat_replace(std::string& cmd, const PRM_ENC& pe, const SYSTEM_DATA& sys_dat, const CONF_GUIEX& conf, const OUTPUT_INFO& oip) { | |
std::string log_path; | |
getLogFilePath(log_path, pe, sys_dat, conf, oip); | |
replace_all(cmd, "%{logpath}", log_path); | |
std::string chap_file; | |
if (pe->muxer_to_be_used >= 0) { | |
const MUXER_CMD_EX *muxer_mode = (sys_dat.exstg->s_mux + pe.muxer_to_be_used)->ex_cmd; | |
const int muxer_mode_i = (pe.muxer_to_be_used == MUXER_MKV) ? conf.mux.mkv_mode : conf.mux.mp4_mode; | |
chap_file = std::string(muxer_mode[muxer_mode_i]->chap_file); | |
cmd_replace(chap_file, pe, sys_dat, conf, oip); | |
} | |
replace(cmd, nSize, "%{chapter}", chap_file); | |
replace(cmd, nSize, "%{chap_apple}", get_chapter_apple(chap_file, pe, sys_dat)); | |
} | |
namespace run_bat{ | |
std::string create_tmp_bat(const char *batfile, const PRM_ENC& pe, const SYSTEM_DATA& sys_dat, const CONF_GUIEX& conf, const OUTPUT_INFO& oip){ | |
try{ | |
const auto bat_tmp = apply_appendix(std::string(batfile), "_tmp.bat"); | |
std::ifstream origin(batfile); | |
std::ostream tmp(bat_tmp, std::ios_base::out | std::ios_base::binary); | |
for(std::string line_buf, std::getline(origin, line_buf), line_buf.clear()){ | |
const auto found = line_buf.find_last_not_of(" \t\f\v\n\r"); | |
if (found != std::string::npos) continue;//すべて空白類文字 | |
line_buf.erase(found + 1); | |
cmd_replace(line_buf, pe, sys_dat, conf, oip); | |
bat_replace(line_buf, pe, sys_dat, conf, oip); | |
tmp << line_buf << "\r\n"; | |
} | |
return bat_tmp; | |
} | |
catch(std::exception&){ | |
return std::string(""); | |
} | |
} | |
AUO_RESULT run(std::string& bat, const SYSTEM_DATA& sys_dat, const CONF_GUIEX& conf, DWORD run_bat_mode){ | |
AUO_RESULT ret = AUO_RESULT_SUCCESS; | |
PROCESS_INFORMATION pi_bat; | |
set_window_title("バッチファイル処理", PROGRESSBAR_MARQUEE); | |
const auto minimized = sys_dat.exstg->s_local.run_bat_minimized; | |
const auto rp_ret = RunProcess(bat_args.c_str(), sys_dat.aviutl_dir, &pi_bat, nullptr, NORMAL_PRIORITY_CLASS, FALSE, minimized); | |
if (RP_SUCCESS != rp_ret) { | |
ret |= AUO_RESULT_ERROR; | |
error_run_process("バッチファイル処理", rp_ret); | |
} | |
if (!ret && !(conf.oth.dont_wait_bat_fin & run_bat_mode)) | |
while (WAIT_TIMEOUT == WaitForSingleObject(pi_bat.hProcess, LOG_UPDATE_INTERVAL)) | |
log_process_events(); | |
set_window_title(AUO_FULL_NAME, PROGRESSBAR_DISABLED); | |
return ret; | |
} | |
} | |
AUO_RESULT run_bat_file_cpp(const CONF_GUIEX *conf, const OUTPUT_INFO *oip, const PRM_ENC *pe, const SYSTEM_DATA *sys_dat, DWORD run_bat_mode){ | |
if(!(conf->oth.run_bat & run_bat_mode)) return AUO_RESULT_SUCCESS; | |
const char *batfile = conf->oth.batfiles[get_run_bat_idx(run_bat_mode)]; | |
if (!PathFileExists(batfile)) { | |
warning_no_batfile(batfile); return AUO_RESULT_ERROR; | |
} | |
const auto bat_tmp = run_bat::create_tmp_bat(batfile, *pe, *sys_dat, *conf, *oip); | |
if(bat_tmp.empty()) return AUO_RESULT_ERROR; | |
return run_bat::run("\"" + bat_tmp + "\"", *sys_dat, *conf, run_bat_mode); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
もう疲れた。
一部補足。
変数名にdpnxとかdpnとかありますが、これはWindowsのバッチファイルにある、変数の展開機能からイメージしてつけてます。
http://pf-j.sakura.ne.jp/program/dos/doscmd/str_percent.htm
の略だろ、きっと