/*<Header>==============================================================
*
*	ＣＤプレーヤ / "MAIN.C"
*
*		[ EIN(tm) project : サンプルプログラム ]
*
*	COPYRIGHT  Nam  1994, All rights reserved.
*
*	配付・組込・改変・商利用すべて自由。ただし無保証っす
*
*-----------------------------------------------------------------------
*	V1.0L01α	94.04.07/Nam	プロトタイプ
*	V1.0L30		94.07.19/Nam	EIN(TM)公開版
*	V1.0L31		94.09.05/Nam	GM_QUIT時に自分でWINDOWを消去
*</Header>==============================================================*/
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<snd.h>
#include	<winb.h>
#include	<te.h>
#include	<fntb.h>
#include	<gui.h>
#include	<egb.h>
//#include	<file_dlg.h>
//#include	<tifflib.h>
#include	<msdos.cf>
#include	<loader.h>
#include	<math.h>
#include	<io.h>
#include	<guidbg.h>
//#include	<wgb.h>
// ※ ここまでが平均的に使用されるヘッダ

#include	"..\ein\eintm.h"	// EIN(TM)関連ライブラリのヘッダ

#define	ERROR	(-1)

int		ID_ICON[10];
int		ID_PANEL[20];
int		dispMode = 0;	// 0:ICON / 1:PANEL
int		showTime = 0;	// 0:トラック内演奏時間, 1:ディスク内演奏時間, 2:

/*= リジューム用設定=================================================*/
int		RSM_DISPMODE;
int		RSM_SHOWTIME;
FRAME	RSM_ICONFR;
FRAME	RSM_PANELFR;
// リジュームマネージャに通知する、アプリ識別ID（63文字以下のuniqな文字列）
char	RSMID[]="%%% CDPlayer icon %%%";
// リジューム情報に埋め込むタイトル文字列（タスクリストにも併用）
char	RSMTITLE[]="ＣＤプレーヤ  V0.1 L31";
// リジューム情報読み書きバッファのサイズ（アプリ固有サイズなので調整してね）
#define	RBUFSIZE	(1024)
/*= リジューム用設定=================================================*/

void	( *GV_defIdleTask )() ;

MMICTRL	mmic = {
				 SCREEN16 | SCREENIGNORE,		//	resolution
				 SCREENUNUSED,
				 0, SCREENAVAILABLE, 0,	//	write_page,display_page,priority
				 SCREENAVAILABLE,	//	mode
				 SCREENEXPAND,		//	vram_x
				 0,0,0,0,			//	size,*ptr,asize,*atpr
				 0,0,0,0,			//	frame
				 -32767,			//	move
				 -32767,
				  32767,
				  32767,
				 15,8,7,15			//	color
				} ;

/*===================================================================*/
/*  メインループ                                                     */
/*===================================================================*/
void main()
{
	extern int APL_init() ;

	int		kobj;

	//	初期化処理
	if (MMI_Open( &mmic ) == NOERR){
		// 二重起動のcheck
		if ( (kobj = MMI_CallMessage( MMI_GetApliId(), GM_QUERYID, QM_KIND, 1)) > NOERR ){
			MMI_CallMessage( MMI_GetApliId(), GM_SWITCH, FALSE, kobj );
		} else {
			// アイドルタスクに登録
			setIdleTask() ;
			// 初期化に成功すればメインループに入る.
			if ( APL_init()==NOERR ){
				MMI_ExecSystem();
			}
			// アイドルの解除
			resetIdleTask();
			// ウィンドゥ消去(※SHELLに消去させると遅いので)
			eraseWin();
		}
	}
	// 終了処理
	MMI_Close() ;
}

/*===================================================================*/
/*  初期化処理                                                       */
/*===================================================================*/
int APL_init()
{
	extern	int		clearCDstat();
	extern	int		updateCDdisp();		// gui.c
	extern	int		userFunc();
	
	extern	MMIINIT	initDataRES_ICON ;
	extern	MMIINIT	initDataRES_PANL ;

	extern	int ICONmaxId;
	extern	unsigned char *ICONTbl[];

	char	work[RSMWORKSIZE];	// リジュームマネージャのワークエリア
	char	buf[RBUFSIZE];
	char	*ptr;
	int		size, x, y;
	HYPER	hyp;
	register int	ret ;

	if ((ret = MMI_initHyper()) < 0)			//	ハイパー型
		return ret;
	if ((ret = MMI_initDialogL40()) < 0)		//	ダイアログ型
		return ret;
//	if ((ret = MMI_initAlertL40()) < 0)			//	アラート型
//		return ret;
	if ((ret = MMI_initMessageL40()) < 0)		//	メッセージ型
		return ret;
//	if ((ret = MMI_initMenuL40()) < 0)			//	メニュー型
//		return ret;
	if ((ret = MMI_initButtonL40()) < 0)		//	ボタン型
		return ret;
	if ((ret = MMI_initDrawButtonL40()) < 0)	//	ドロウボタン型
		return ret;
//	if ((ret = MMI_initToggleIconL40()) < 0)	//	トグルボタン型
//		return ret;
	if ((ret = MMI_initIconL40()) < 0)			//	アイコン型
		return ret;
//	if ((ret = MMI_initScrollBarL40()) < 0)		//	スクロールバー型
//		return ret;
//	if ((ret = MMI_initTextL40()) < 0)			//	テキスト型
//		return ret;
//	if ((ret = MMI_initMenuItemL40()) < 0)		//	メニューアイテム型
//		return ret;
	if ((ret = MMI_initWindowL40()) < 0)		//	ウィンドウ型
		return ret;

	//	データの登録
	if ((ret = MMI_Init(&initDataRES_ICON)) < 0)
		return ret ;
	if ((ret = MMI_Init(&initDataRES_PANL)) < 0)
		return ret ;

	/*----------------------------------*/
	/*	アイコン登録					*/
	/*----------------------------------*/
	MMI_SetIconTable( ICONTbl, ICONmaxId ) ;

	// 256,32kの時のGUI色を設定
	EIN_initGuiColor();

	//	スイッチャー対応関数の登録
	MMI_SendMessage( MMI_GetBaseObj(), MM_SETEXEC, 1, userFunc ) ;

	//	タイトルの登録
	MMI_CallMessage( MMI_GetApliId(), GM_TITLE, (int)RSMTITLE, 0 ) ;

	/*----------------------------------*/
	/*	リジューム読み込み (※のついた処理は必ず行ってください)	*/
	/*----------------------------------*/
	// ※リジュームマネージャの初期化(アプリのIDタグ登録)
	EIN_rsmInit( work, RSMID );
	// ※読み込みバッファ設定
	EIN_rsmBufSet( work, buf, RBUFSIZE );
	// ※リジューム情報読み込み
	size = EIN_rsmLoad( work );
	#ifdef DEBUG
	printf(" resume size(%d)\n",size);
	#endif
	if ( size > 0 ){
		// 表示モード( 0:ICON / 1:PANEL,  ... )
		if (((ptr = strstr(buf,"\nMODE: ")) != NULL ) &&
			(sscanf(ptr,"\nMODE: %d %d\n", &x, &y) > 1 ) ){
			dispMode = ( (x<0)||(x>1) ) ?0 :x;
			showTime = ( (y<0)||(y>2) ) ?0 :y;
			RSM_DISPMODE = dispMode;
			RSM_SHOWTIME = showTime;
		}
		// ICON表示位置
		if (((ptr = strstr(buf,"\nICON: ")) != NULL ) &&
			(sscanf(ptr,"\nICON: %d %d\n", &x, &y) > 1 ) ){
			MMI_SendMessage( ID_ICON[0], MM_GETHYPER, 1, &hyp );	// 枠座標を得る
			RSM_ICONFR.lupx = x;
			RSM_ICONFR.lupy = y;
			RSM_ICONFR.rdwx = x+(hyp.fr.rdwx-hyp.fr.lupx);
			RSM_ICONFR.rdwy = y+(hyp.fr.rdwy-hyp.fr.lupy);
			#ifdef DEBUG
			printf("ICON: move to (%d,%d)\n", x, y);
			#endif
			if ( x<-31 ){
				x=0;
			}
			if ( y<-31 ){
				y=0;
			}
			MMI_SendMessage( ID_ICON[0], MM_MOVE, 1, &RSM_ICONFR ) ;
		}
		// PANEL表示位置
		if (((ptr = strstr(buf,"\nPANEL: ")) != NULL ) &&
			(sscanf(ptr,"\nPANEL: %d %d\n", &x, &y) > 1 ) ){
			MMI_SendMessage( ID_PANEL[0], MM_GETHYPER, 1, &hyp );	// 枠座標を得る
			RSM_PANELFR.lupx = x;
			RSM_PANELFR.lupy = y;
			RSM_PANELFR.rdwx = x+(hyp.fr.rdwx-hyp.fr.lupx);
			RSM_PANELFR.rdwy = y+(hyp.fr.rdwy-hyp.fr.lupy);
			#ifdef DEBUG
			printf("PANEL: move to (%d,%d)\n", x, y);
			#endif
			if ( (x>=0)&&(x<1024)&&(y>=0)&&(y<712) ){
				MMI_SendMessage( ID_PANEL[0], MM_MOVE, 1, &RSM_PANELFR ) ;
			}
		}
	} else {
		#ifdef DEBUG
		printf("Can't find resume file.\n");
		#endif
	}

	//	ウィンドウ類をATTACHする
	if ( dispMode == 0 ){
		MMI_SendMessage( ID_ICON[0], MM_ATTACH, 1, MMI_GetBaseObj() ) ;
	} else {
		MMI_SendMessage( ID_PANEL[0], MM_ATTACH, 1, MMI_GetBaseObj() ) ;
	}

	//	背景を表示する
	MMI_SendMessage( MMI_GetBaseObj(), MM_SHOW, 0 ) ;

	// CD情報を表示
	clearCDstat();
	updateCDdisp( 1 );

	return NOERR ;
}

/*===================================================================*/
/* リジューム情報更新 (※がついた処理は必ず行って下さい)             */
/*===================================================================*/
void	SaveResumeFile()
{
	char	work[RSMWORKSIZE];
	
	char	buf[RBUFSIZE];
	char	aplpath[128];
	HYPER	hyp1,hyp2;
	
	int		ret;
	
	// 枠座標を得る
	MMI_SendMessage( ID_ICON[0], MM_GETHYPER, 1, &hyp1 );
	MMI_SendMessage( ID_PANEL[0],MM_GETHYPER, 1, &hyp2 );
	// 変化していたらセーブ
	if ( (RSM_DISPMODE     != dispMode )||
//		 (RSM_SHOWTIME     != showTime )||
		 (RSM_ICONFR.lupx  != hyp1.fr.lupx)||
		 (RSM_ICONFR.lupy  != hyp1.fr.lupy)||
		 (RSM_PANELFR.lupx != hyp2.fr.lupx)||
		 (RSM_PANELFR.lupy != hyp2.fr.lupy) ){
		// ※マネージャ初期化
		EIN_rsmInit( work, RSMID );
		// ※バッファ設定(アプリ識別ID,更新時刻は自動設定されます)
		EIN_rsmBufSet( work, buf, RBUFSIZE );
		// ※アプリディレクトリ保存
		MMI_CallMessage( MMI_GetApliId(), GM_QUERYID, QM_PATH, (int)aplpath );
		EIN_rsmBufPrintf( work, "APLPATH: %s", aplpath );
		// ※アプリ名保存
		EIN_rsmBufPrintf( work, "TITLE:   %s", RSMTITLE );
		// ※コメント保存
		EIN_rsmBufCat( work, "COMMENT: アイコンサイズのＣＤプレーヤです。ダブルクリックで大きくできます。" );
		// 表示モード保存
		EIN_rsmBufPrintf( work, "MODE: %d %d", dispMode, showTime );
		// アイコン位置保存
		EIN_rsmBufPrintf( work, "ICON: %d %d", hyp1.fr.lupx, hyp1.fr.lupy );
		// パネル位置保存
		EIN_rsmBufPrintf( work, "PANEL: %d %d", hyp2.fr.lupx, hyp2.fr.lupy );
		// ※バッファをセーブ
		ret = EIN_rsmSave( work );
		#ifdef DEBUG
		printf(" resume save size(%d)   ptr:(%d,%d)\n",ret, hyp1.fr.lupx, hyp1.fr.lupy);
		#endif
		RSM_DISPMODE= dispMode;
		RSM_ICONFR  = hyp1.fr;
		RSM_PANELFR = hyp2.fr;
	}
}

/*===================================================================*/
/*  イベントループ関数                                               */
/*===================================================================*/
int		userFunc( int apliId, int messId, int info, int data )
{
	extern	int	updateCDdisp();		// icon.c
	extern	int	clearCDstat();		// cdp.c

	register	int		ret;

	ret = ILLEGAL_FUNCTION ;
	switch( messId ){
		//	他タスクからスイッチしてきた
		case GM_WAKE :
			clearCDstat();		//	タイトルをアクティブ色に
			updateCDdisp( 1 );	//	CD表示を更新
			break ;

		//	他タスクにスイッチする
		case GM_SLEEP :
			//	タイトルをインアクティブ色に
			break ;

		//	終了要求が出た
		case GM_QUIT :
			// リジューム
			SaveResumeFile();
			//	正常終了
			MMI_SetHaltFlag( TRUE ) ;	//	イベントループを終了させるフラグ
			ret = NOERR ;
			break ;
	}

	return ret ;
}

/*===================================================================*/
/*  アイドル関数                                                     */
/*===================================================================*/
void	userIdleTask()
{
	extern	int	updateCDdisp();		// icon.c

	updateCDdisp( 0 );
}

/*===================================================================*/
/*  アイドルタスクに登録                                             */
/*===================================================================*/
int		setIdleTask()
{
	extern void	userIdleTask();		// gui.c
	
	void	( *idleTask )() ;

	/*	アイドル処理関数の取得	*/
	idleTask = MMI_GetIdleTaskFunc() ;

	/*	二重登録禁止チェック	*/
	if( idleTask != userIdleTask ){
		GV_defIdleTask = idleTask ;
		MMI_SetIdleTaskFunc( (void ((*)(void)))userIdleTask );
	}

	return ERROR ;
}

/*===================================================================*/
/*  アイドルタスクから削除                                           */
/*===================================================================*/
int		resetIdleTask()
{
	extern void	userIdleTask();		// gui.c
	
	void	( *IdleTask )() ;

	/*	アイドル処理関数の取得	*/
	IdleTask = MMI_GetIdleTaskFunc() ;

	/*	USER関数登録のチェック	*/
	if( IdleTask == userIdleTask ){
		MMI_SetIdleTaskFunc( GV_defIdleTask ) ;
		GV_defIdleTask = 0 ;
	}

	return ERROR ;
}

/*===================================================================*/
/*  ウィンドゥ消去                                                   */
/*===================================================================*/
int		eraseWin()
{
	register	int		foo;
	// ウィンドゥ消去(※SHELLに消去させると遅いので)
	if ( dispMode == 0 ){	// 0:ICON / 1:PANEL
		foo = ID_ICON[0];
	} else {
		foo = ID_PANEL[0];
	}
	MMI_SendMessage( foo, MM_SLEEP, 0 );
	MMI_SendMessage( foo, MM_ERASE, 0 );
	MMI_SendMessage( foo, MM_DETACH, 0 );
	return NOERR;
}
