/****************************************************************************
 *
 * CRI Middleware SDK
 *
 * Copyright (c) 2001-2004 CRI-MW
 *
 * Appli.   : AIX Sample Program 
 * Module   : Main function.(Playing AIX File)
 * File     : aixgdply.c
 *
 ****************************************************************************/

/***************************************************************************
 *		インクルードファイル
 *		Include file
 ***************************************************************************/

#include <cri_mw.h>
#include "usr/usr.h"

/***************************************************************************
 *		定数マクロ
 *		Constant Macro
 ***************************************************************************/

/*	最大チャンネル数				*/
/*	The number of maximum channels	*/
#define	MAX_CH		(2)

/*	同時再生最大ストリーム数									*/
/*	The number of maximum disc streams playing at the same time	*/
#define	MAX_STM		(1)

/*	最高サンプリング周波数		*/
/*	Maximum sampling frequency	*/
#define	MAX_SFREQ	(48000)

/*	最大トラック数					*/
/*	The number of maximum tracks	*/
#define	MAX_NTR		(4)

/*	ファイル再生用ワーク領域の大きさ	*/
/*	Work area size of disc stream play	*/
#define	WKSIZE		(AIXP_CALC_WORK(MAX_CH, MAX_STM, MAX_SFREQ, MAX_NTR))

/***************************************************************************
 *		処理マクロ
 *		Process MACRO
 ***************************************************************************/
/*	フラグON/OFFの反転		*/
/*	Turn over flag(ON/OFF)	*/
#define NOT_FLAG(flag)		(((flag) == OFF) ? ON : OFF)
#define UNUSED(val)			((val) = (val))

/***************************************************************************
 *		変数定義
 *		Variable Definition
 ***************************************************************************/
/*	アプリケーション構造体											*/
/*	Application structure											*/
typedef struct {
	AIXP	aixp;					//	AIXP handle
	ADXT	adxt[MAX_NTR];			//	ADXT handle
	Sint8	mute[MAX_NTR];			//	Mute flag
	Char8	*fname;					//	File name
	Sint8	wk[WKSIZE];				//	Work area for AIXP
	Sint8	*ampwk[MAX_NTR];		//	Work area for Amplitude
} AP_OBJ;

/*	アプリケーションオブジェクト									*/
/*	Application Object												*/
AP_OBJ ap_obj = {
	NULL,						//	AIXP handle
	{NULL,NULL,NULL,NULL},		//	ADXT handle
	{OFF,OFF,OFF,OFF},				//	Mute flag
	"moon48.aix",				//	File name
};

/***************************************************************************
 *		関数宣言
 *		Function Declaration
 ***************************************************************************/
void ap_adx_err_func(void *obj, Char8 *msg);
void ap_disp_info(AP_OBJ *ap);
void ApInitMw(AP_OBJ *ap);
void ApFinishMw(AP_OBJ *ap);
void ApStart(AP_OBJ *ap);
void ApStop(AP_OBJ *ap);
Sint32 ApExec(AP_OBJ *ap);

/***************************************************************************
 *		関数定義
 *		Function Definition
 ***************************************************************************/

/*	ADXTエラー発生時に起動する関数					*/
/*	Callback function when an error occur in ADXT	*/
void ap_adx_err_func(void *obj, Char8 *msg)
{
	UNUSED(obj);		// 未使用変数

	UsrDbgPrintf(msg);

	for (;;) {		/*	リリース時には無くす					*/
		;			/*	Delete when you release application.	*/
	}
}

/*	情報の表示			*/
/*	Display infomation	*/
void ap_disp_info(AP_OBJ *ap)
{
	Char8 *mute_str[2] = {"OFF", "ON "};
	ADXT adxt;
	Char8 		*ststr[] =
		{"STOP   ", "PREP   ", "PLAYING", "PLAYEND",  "ERROR "};
	Sint32		stat, sfreq, cnt;
	Sint32		hh, mm, ss, ff;
	Sint32		vol[MAX_NTR][MAX_CH], i, j, k;

	stat = AIXP_GetStat(ap->aixp);
	adxt = AIXP_GetAdxt(ap->aixp, 0);
	ADXT_GetTime(adxt, &cnt, &sfreq);
	UsrSfcnt2time(sfreq,  cnt, &hh, &mm, &ss, &ff);

	UsrPrintf(2,  3,  "AIX Sample Program");
	UsrPrintf(3,  5,  "STAT = %s (%d)", ststr[stat], stat);
	UsrPrintf(3,  6,  "TIME = %2d:%02d:%02d.%02d", hh, mm, ss, ff);
	UsrPrintf(3,  8,  "TRACK     MUTE VOLUME");
	UsrPrintf(3,  9,  "1(Drums ) %s  L -------- R --------",
					mute_str[ap->mute[0]]);
	UsrPrintf(3, 10,  "2(Base  ) %s  L -------- R --------",
					mute_str[ap->mute[1]]);
	UsrPrintf(3, 11,  "3(Melody) %s  L -------- R --------",
					mute_str[ap->mute[2]]);
	UsrPrintf(3, 12,  "4(Code  ) %s  L -------- R --------",
					mute_str[ap->mute[3]]);

	for (i = 0; i < MAX_NTR; i++) {
		for (j = 0; j < MAX_CH; j++) {
			vol[i][j] = ADXT_GetAmplitude(ap->adxt[i], j);
			for (k = 0; k < vol[i][j] / 3000; k++) {
				UsrPrintf(20+k+j*11,  9+i,  "#");	
			}
		}
	}

}

/*	ミドルウェアの初期化				*/
/*	Initialize Middleware				*/
void ApInitMw(AP_OBJ *ap)
{
	UNUSED(ap);

	ADXT_Init();
	AIXP_Init();
}

/*	ミドルウェアの終了					*/
/*	Finalize Middleware					*/
void ApFinishMw(AP_OBJ *ap)
{
	UNUSED(ap);
	AIXP_Finish();
	ADXT_Finish();
}

/*	アプリケーション開始処理	*/
/*	Start application			*/
void ApStart(AP_OBJ *ap)
{
	Sint32 i, wksize;

	if ((ap->aixp = AIXP_Create(MAX_NTR, MAX_CH, ap->wk, sizeof(ap->wk))) == NULL) {
		for (;;) ;
	}

	wksize = ADXT_CalcAmpWork(MAX_CH);
	for (i = 0; i < MAX_NTR; i++) {
		ap->adxt[i] = AIXP_GetAdxt(ap->aixp, i);
		if ((ap->ampwk[i] = UsrMalloc((Uint32)wksize)) == NULL) {
			for (;;) ;
		}
		ADXT_SetAmpWork(ap->adxt[i], ap->ampwk[i], wksize);
	}
	for (i = 0; i < MAX_NTR; i++) {
		ap->mute[i] = OFF;
	}

	AIXP_SetLpSw(ap->aixp, ON);
	AIXP_StartFname(ap->aixp, ap->fname, NULL);
}

/*	アプリケーション停止処理	*/
/*	Stop application			*/
void ApStop(AP_OBJ *ap)
{
	Sint32	i;
	
	AIXP_Destroy(ap->aixp);
	ap->aixp = NULL;
	for (i = 0; i < MAX_NTR; i++) {
		UsrFree(ap->ampwk[i]);
		ap->ampwk[i] = NULL;
	}
}

/*	アプリケーションメイン処理	*/
/*	Run application				*/
Sint32 ApExec(AP_OBJ *ap)
{
	const USR_PERIPHERAL	*peri;

	ap_disp_info(ap);

	peri = UsrGetPeripheral(USR_PD_PORT1);
	if (peri->on & UTPAD_START)
		return FALSE;

	if (peri->press & UTPAD_BUTTON1) {
		if (ap->mute[0] == OFF) {
			AIXP_SetTrackVol(ap->aixp, 0, -960);
			ap->mute[0] = ON;
		} else {
			AIXP_SetTrackVol(ap->aixp, 0, 0);
			ap->mute[0] = OFF;
		}
	}
	if (peri->press & UTPAD_BUTTON2) {
		if (ap->mute[1] == OFF) {
			AIXP_SetTrackVol(ap->aixp, 1, -960);
			ap->mute[1] = ON;
		} else {
			AIXP_SetTrackVol(ap->aixp, 1, 0);
			ap->mute[1] = OFF;
		}
	}
	if (peri->press & UTPAD_BUTTON3) {
		if (ap->mute[2] == OFF) {
			AIXP_SetTrackVol(ap->aixp, 2, -960);
			ap->mute[2] = ON;
		} else {
			AIXP_SetTrackVol(ap->aixp, 2, 0);
			ap->mute[2] = OFF;
		}
	}
	if (peri->press & UTPAD_BUTTON4) {
		if (ap->mute[3] == OFF) {
			AIXP_SetTrackVol(ap->aixp, 3, -960);
			ap->mute[3] = ON;
		} else {
			AIXP_SetTrackVol(ap->aixp, 3, 0);
			ap->mute[3] = OFF;
		}
	}
	if (AIXP_GetStat(ap->aixp) == AIXP_STAT_PLAYEND)
		return FALSE;

	/* CRI Middleware Library's Server function */
	ADXM_ExecMain();

	return TRUE;
}

/***
 *		メイン処理
 *		MAIN
 ***/
int main(void)
{
	AP_OBJ	*ap;
	Sint32	term_flag = OFF;
	Bool	ret;

	ap = &ap_obj;

	/*	エラーコールバック関数の登録		*/
	/*	Entry ADX error callback function	*/
	ADXM_SetCbErr(ap_adx_err_func, NULL);

	/*	システムの初期化										*/
	/*	Initialize System										*/
	UsrInitSystem(NULL, NULL);
	
	/*	ビデオの初期化											*/
	/*	Initialize Video System									*/
	UsrInitVideo(NULL, NULL);
	
	/*	サウンドの初期化										*/
	/*	Initialize Sound System									*/
	UsrInitSound(NULL, NULL);

	ApInitMw(ap);

	while (term_flag == OFF) {
		ApStart(ap);
		/*	cnt :frame count						*/
		/*	cnt=0:interlace	/ cnt>0:non interlace	*/
		UsrInitSync(2);
		for (;;) {
			UsrSyncFrame();
			UsrBeginDraw();
			ret = ApExec(ap);
			UsrEndDraw();

			/* 終了するかどうかの確認					*/
			/* Checks whether Usr module is terminated	*/
			if (UsrIsTerminated() == TRUE) {
				term_flag = ON;
			}
			
			if (ret == FALSE || term_flag == ON) {
				break;
			}
		}
		ApStop(ap);
	}
	/*	アプリケーション終了処理	*/
	/*	Finalize application		*/
	ApFinishMw(ap);			/*	ミドルウェアの終了				*/
							/*	Finalize Middleware				*/
	UsrFinishSound();		/*	サウンドシステムの終了処理		*/
							/*	Finalize sound system			*/
	UsrFinishVideo();		/*	ビデオの終了処理				*/
							/*	Finalize Video system			*/
	UsrFinishSystem();		/*	システムの終了処理				*/
							/*	Finalize system					*/
	return 0;
}

/* end of file */
