Skip to content

Instantly share code, notes, and snippets.

@yumetodo
Last active August 29, 2015 14:27
Show Gist options
  • Save yumetodo/cc48d6543d9320a9fe6c to your computer and use it in GitHub Desktop.
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)を作った。ビルドテストなんてしてない。
#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);
}
@yumetodo
Copy link
Author

もう疲れた。

一部補足。
変数名にdpnxとかdpnとかありますが、これはWindowsのバッチファイルにある、変数の展開機能からイメージしてつけてます。

http://pf-j.sakura.ne.jp/program/dos/doscmd/str_percent.htm

略記 省略前
d drive
p path
n file name
x file extinction

の略だろ、きっと

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment