/*
 *	app.cpp
 *
 *	AdxProbe.exe - Sofdec情報表示ツール
 *	Copyright (C) 2017 Naoyuki Sawa
 *
 *	* Wed Mar 22 22:14:37 JST 2017 Naoyuki Sawa
 *	- 1st リリース。
 *	  /clip/tool/SofdecProbe/を元にして作成しました。
 *	* Mon Apr 03 23:36:16 JST 2017 Naoyuki Sawa
 *	- 暗号化されたデータの情報取得に対応しました。
 *	  実際には、ムービーデータと違って音声データは復号キーが合っていなくても情報は取得出来るのですが、一応対応しておく事にしました。
 *	  詳細は、/clip/tool/SofdecHelper/SofdecHelper.cの同日のコメントを参照して下さい。
 *	* Sun Apr 09 22:05:18 JST 2017 Naoyuki Sawa
 *	- /clip/tool/SofdecHelper/SofdecHelper.cの更新に伴い、当ツールもリビルドしました。
 *	  詳細は、/clip/tool/SofdecHelper/SofdecHelper.cの同日のコメントを参照して下さい。
 *	* Tue Apr 18 21:46:46 JST 2017 Naoyuki Sawa
 *	- /clip/tool/SofdecHelper/ をリビルドした事に伴い、当ツールもリビルドしました。
 *	  詳細は、/clip/tool/SofdecHelper/SofdecHelper.cの同日のコメントを参照して下さい。
 *	  当ツールのソースコード,及び,当ツールの動作には変更有りません。
 */
#include "app.h"
#define VERSION		"20170418"	//最終更新日
/****************************************************************************
 *	main
 ****************************************************************************/
int main(int argc, char* argv[]) {
	int exitCode = EXIT_SUCCESS;
#ifdef  _DEBUG
	remove("syslog.out");			//毎回ログを削除する事にした。
    #ifndef USE_JOB_DEBUG
	openlog(NULL, LOG_PERROR, LOG_USER);	//デバッグビルドでは、システムログを標準エラーにも出力する。ただし、デバッグジョブを使用する場合は、デバッグジョブのcurses表示と衝突しないよう、標準エラーには出力しない。
    #endif//USE_JOB_DEBUG
#else //_DEBUG
	setlogmask(LOG_UPTO(LOG_INFO));		//リリースビルドでは、LOG_DEBUGを抑制する。
#endif//_DEBUG
#if     (defined(GC_H) && !defined(USE_BISON_FLEX))
//	putenv("GC_LOG_FILE=CON");//ログ出力先を指定する。
//	GC_set_find_leak(1);//メモリリーク検出を開始する。
#endif//(defined(GC_H) && !defined(USE_BISON_FLEX))
#ifdef  __CLIP_SEH_H__
	SEH_init();
#endif//__CLIP_SEH_H__
#ifdef  USE_GDIPLUS
	Gdiplus_Init();
#endif//USE_GDIPLUS
	app_init(argc, argv);
	exitCode = app_main(argc, argv);
	app_exit();
#ifdef  USE_GDIPLUS
	Gdiplus_Exit();
#endif//USE_GDIPLUS
#if     (defined(GC_H) && !defined(USE_BISON_FLEX))
//	CHECK_LEAKS();//メモリリークを検出する。
#endif//(defined(GC_H) && !defined(USE_BISON_FLEX))
	return exitCode;
}
/****************************************************************************
 *	usage
 ****************************************************************************/
__declspec(noreturn) static void usage() {
	fprintf(stderr, "AdxProbe.exe - Adx情報表示ツール (%s)\n", VERSION);
	fprintf(stderr, "Copyright (C) 2017 Naoyuki Sawa\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "USAGE:\n");
	fprintf(stderr, "  AdxProbe.exe [option ...] filename[.hca] [filename[.hca] ...]\n");
	fprintf(stderr, "  ・filenameは、ワイルドカードによる複数指定も可能です。\n");
	fprintf(stderr, "  ・filenameの拡張子が省略されていたら、'.hca'とします。\n");
	fprintf(stderr, "  ・filenameは相対パスで指定して下さい。絶対パスで指定するとエラーが発生します。\n");		//絶対パスがエラーになる理由は、criFsBinder_BindDirectory()でフォルダにバインドすると、バインダが絶対パスを検索しないようだからです。相対パス形式で親フォルダへ辿って行く事は可能です。
	fprintf(stderr, "\n");
	fprintf(stderr, "OPTIONS:\n");
	fprintf(stderr, "  -c               CSV形式で出力します。\n");
	fprintf(stderr, "                   このオプションを指定しなければ、読み易い形式で出力します。\n");
//{{2017/04/03追加:暗号化されたデータの     情報取得に対応しました。
	fprintf(stderr, "  -k復号キー       暗号化された音声データの復号キー(0以外の値)を指定します。\n");
	fprintf(stderr, "                   このオプションを指定しなければ、暗号化されていない音声データと見なします。\n");
//}}2017/04/03追加:暗号化されたデータの情報取得に対応しました。
	fprintf(stderr, "  -h               使い方を表示します。\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "OUTPUT FIELDS:\n");
	fprintf(stderr, "  format           フォーマット種別\n");
	fprintf(stderr, "  sampling_rate    サンプリング周波数\n");
	fprintf(stderr, "  num_samples      総サンプル数\n");
	fprintf(stderr, "  loop_offset      ループ開始サンプル\n");
	fprintf(stderr, "  loop_length      ループ区間サンプル数\n");
	fprintf(stderr, "  num_channels     チャンネル数\n");
	exit(EXIT_FAILURE);
}
/****************************************************************************
 *	
 ****************************************************************************/
void app_init(int argc, char* argv[]) {
	/** no job **/
}
/*--------------------------------------------------------------------------*/
void app_exit() {
	/** no job **/
}
/*--------------------------------------------------------------------------*/
int app_main(int argc, char* argv[]) {
	int exitCode = EXIT_SUCCESS;
	int opt_c = 0;	//'-c'オプションが指定されたら1にする。
	int opt_k = 0;	//'-k'オプションが指定されたら復号キー(0以外)を格納する。	//{{2017/04/03追加:暗号化されたデータの情報取得に対応しました。}}
	//コマンドラインオプションを処理する。
	{
		int opt;
		opterr = 0; //オプションエラーは当プログラム内で処理するので、getopt()内でのエラー表示は不要。
		while((opt = getopt(argc, argv, "ck:h")) != -1) {	//コマンドラインオプションを処理する。
			switch(opt) {
			case 'c':
				opt_c = 1;
				break;
//{{2017/04/03追加:暗号化されたデータの情報取得に対応しました。
			case 'k':
				opt_k = _atoi64(optarg);	//VC++6.0にはstrtoll()やstrtoull()が無いので、仕方無く_atoi64()で代用しました。別の案としてstrtod()で取得して整数化する方法も考えましたが、_atoi64()の方が(非標準ではありますが)自然だと思うので_atoi64()にしました。
				if(!opt_k) { usage(); }
				break;
//}}2017/04/03追加:暗号化されたデータの情報取得に対応しました。
			case 'h':
			default:
				usage();
			}
		}
	}
	//少なくとも一個以上サウンドファイル名が指定されていなければいけない。
	if(optind >= argc) { usage(); }
	//ライブラリを初期化する。
	{
//{{2017/04/03変更:暗号化されたデータの情報取得に対応しました。
//		static const ST_SofdecHelperInfo stSofdecHelperInfo = {
//			//--- SofdecHelper ---
//			1,	//同時再生するムービーの数			0可	//当ツールはムービーを使用してないので本来は0で構わないはずなのですが、実際に0にするとCRIライブラリ側で「E2011030901M:CriManaLibConfig.max_decoder_handles must be at least 1.」というエラーが発生したので、ダミーとして1にしました。
//			NULL,	//ムービーのシームレス連続再生用コールバック	NULL可
//			//--- AdxHelper ---
//			0,	//同時再生するサウンドの数			0可	//AdxHelper_GetFormatInfo()は、再生プールが無くても、一時的なプレーヤを作成してそこから情報を取得出来るので、同時再生するサウンドの数(=再生プールの数)は0で構いません。
//			NULL,	//サウンドのシームレス連続再生用コールバック	NULL可
//		};
//↓2017/04/03変更:暗号化されたデータの情報取得に対応しました。
		ST_SofdecHelperInfo stSofdecHelperInfo;
		memset(&stSofdecHelperInfo, 0, sizeof stSofdecHelperInfo);
		stSofdecHelperInfo.NumMovies	= 1;			//	0可	//当ツールはムービーを使用してないので本来は0で構わないはずなのですが、実際に0にするとCRIライブラリ側で「E2011030901M:CriManaLibConfig.max_decoder_handles must be at least 1.」というエラーが発生したので、ダミーとして1にしました。
	//不要	stSofdecHelperInfo.NumSounds	= 0;			//	0可	//AdxHelper_GetFormatInfo()は、再生プールが無くても、一時的なプレーヤを作成してそこから情報を取得出来るので、同時再生するサウンドの数(=再生プールの数)は0で構いません。
		stSofdecHelperInfo.SoundKey	= opt_k;
//}}2017/04/03変更:暗号化されたデータの情報取得に対応しました。
		SofdecHelper_Init(&stSofdecHelperInfo);
	}
	//各サウンドファイル名について…
	for(;;) {
		char path[MAX_PATH], drive[MAX_DRIVE], dir[MAX_DIR], fname[MAX_FNAME], ext[MAX_EXT];
		ST_AdxHelper_FormatInfo info;
		//サウンドファイル名の拡張子が省略されていたら、'.hca'を補う。
		splitpath(argv[optind], drive, dir, fname, ext);
		makepath(path, drive, dir, fname, ext[0] ? ext : ".hca");
		//フォーマット情報を取得する。
		AdxHelper_GetFormatInfo(path, &info);
		//フォーマット情報を表示する。
		if(!opt_c) {
			//読み易い形式
			printf("\"%s\"\n", path);
			printf("  format        %s\n", info.format);		//フォーマット種別
			printf("  sampling_rate %d\n", info.sampling_rate);	//サンプリング周波数
			printf("  num_samples   %d\n", info.num_samples);	//総サンプル数
			printf("  loop_offset   %d\n", info.loop_offset);	//ループ開始サンプル
			printf("  loop_length   %d\n", info.loop_length);	//ループ区間サンプル数
			printf("  num_channels  %d\n", info.num_channels);	//チャンネル数
		} else {
			//CSV形式
			printf("\"%s\",%s,%d,%d,%d,%d,%d\n",
				path,
				info.format,					//フォーマット種別
				info.sampling_rate,				//サンプリング周波数
				info.num_samples,				//総サンプル数
				info.loop_offset,				//ループ開始サンプル
				info.loop_length,				//ループ区間サンプル数
				info.num_channels);				//チャンネル数
		}
		//サウンドファイル名を次へ進める。
		if(++optind >= argc) { break; }
		//読み易い形式ならば、空行を挟む。
		if(!opt_c) { putchar('\n'); }
	}
	//ライブラリをクリーンアップする。
	SofdecHelper_Exit();
	return exitCode;
}
