/** << MSC V5.1 >> ************************************************************
**
**	-----  ＣＤ演奏プログラム -----------------------------------------------
**	int CDplay( int tocread, int startno, int endno, unsigned char repeat ) ;
**
**	<input>		: tocread - =1(!=0) TOC 情報の取得をする。
**                          =0      TOC 情報の取得はしない。
**              : startno - 演奏開始曲番号
**              : endno   - 演奏終了曲番号
**              : repeat  - リピート回数
**
**	<return>	: = 0 - 正常終了
**				: = 1 - エラー
**
**	----- HISTORY -----
**	1990.02.21 : CREATE
**	1990.07.03 : CDﾄﾞﾗｲﾌﾞのﾃﾞﾊﾞｲｽが登録されていない時のﾒｯｾｰｼﾞ追加｡
**
**	Programmed by Y.Hirata ( Nifty ID : NAB03321 )
**
******************************************************************************/
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	"cdr.h"
#include	<dos.h>

#define		DEBUG		0

#define		TRUE		1
#define		FALSE		0

#define		RETRY		10		/*  エラー発生時のリトライ回数		*/

static char TOCON = FALSE ;		/*  ＴＯＣ情報の取得済か？			*/

#define		Cddrv		0			/*  ＣＤドライブ番号 ( 0 - 6 )	*/
									/*  TOWNSでは Cddrv=0 のみ		*/
int	Cdtype ;						/*	ＣＤタイプ					*/
int	Sttrack ;						/*	先頭トラック(曲)番号		*/
int	Endtrack ;						/*	最終トラック(曲)番号		*/
int	Status ;						/*	音楽の演奏状態				*/
int	Nowmusicno ;					/*	現在演奏中の曲番号			*/

typedef struct _TOC {
		char	min ;
		char	sec ;
		char	frame ;
} TOC ;

static TOC Trtime[99],Endtime,Disctime,Nowtime,Usest,Useet ;
/*
**	Trtime[99] : 各トラックの演奏開始時間
**	Endtime    : ディスク内演奏終了時間
**	Disctime   : ディスク内演奏時間
**	Nowtime    : 演奏中のトラック内演奏時間
**	Usest      : 演奏開始指定時間
**	Useet      : 演奏終了指定時間
*/

/***************************  ＣＤ情報の取得  ********************************/
/*
**	まずは、このルーチンをよんでコンパクトディスク( CD )の情報を取得します。
*/
int cdinfo()
{
	return(
		CDR_cdinfo
		( Cddrv,&Cdtype,&Sttrack,&Endtrack,(char *)Trtime,(char *)&Endtime )
	) ;
}

/*******************************  ＣＤ演奏  **********************************/
/*				
**		さぁ、ミュ〜ジック・スタート！
**		時間指定による音楽演奏をしま〜す！
**
**	<input>		: count - 演奏回数(リピート)
*/
int mtrplay( unsigned char count )
{
	return(
		CDR_mtrplay( Cddrv,(char *)&Usest,(char *)&Useet,count )
	) ;
}

/***************************  ＣＤ演奏状態の取得  ****************************/
/*				
**		今、音楽の演奏状態はど〜なってるかなっ？！
*/
int mphase()
{
	return(
		CDR_mphase
		( Cddrv,&Status,&Nowmusicno,(char *)&Nowtime,(char *)&Disctime )
	) ;
}

/***************************  演奏開始時間の設定  ****************************/
/*
**	<input>		: trackno - 演奏開始トラック(曲番号)
*/
void usestset( int trackno )
{
	if ( trackno<Sttrack )	trackno = Sttrack ;
	if ( trackno>Endtrack )	trackno = Endtrack ;

	if ( Cdtype==3 && trackno==Sttrack ) trackno++ ;

	Usest.sec   = Trtime[trackno-1].sec ;
	Usest.min   = Trtime[trackno-1].min ;
	Usest.frame = Trtime[trackno-1].frame ;

	printf("START (%02d) - ",trackno) ;
}

/*************************  演奏終了時間の設定  ******************************/
/*
**	<input>		: trackno - 演奏終了トラック(曲番号)
*/
void useetset( int trackno )
{
/*	frame : 0 - 74 : 75frame=1sec	*/

	if ( trackno<Sttrack ) trackno = Sttrack ;
	if ( Cdtype==3 && trackno==Sttrack ) trackno++ ;
/*
**	最後の曲まで(または最後の曲だけを)演奏した〜い時には、
**	演奏終了時間の指定に注意しましょう！
**
**	※ 演奏終了時間は、ディスク内演奏終了時間から 1 フレーム引いた値を指定
**	   しないとだめだよ！
*/
	if ( trackno>=Endtrack ) {			/*  最終曲が指定された時	*/
		trackno = Endtrack ;
		Useet.sec = Endtime.sec ;
		Useet.min = Endtime.min ;
		if ( !Endtime.frame ) {
			Useet.frame = 74 ;
			if ( !Endtime.sec ) {
				Useet.sec  = 59 ;
				Useet.min -= 1 ;
			} else
				Useet.sec = Endtime.sec-1 ;
		} else
			Useet.frame = Endtime.frame-1 ;
	} else {							/*  最終曲じゃない時		*/
		Useet.sec   = Trtime[trackno].sec ;
		Useet.min   = Trtime[trackno].min ;
		Useet.frame = Trtime[trackno].frame ;
	}

	printf("END (%02d) : ",trackno) ;
}

/*******************************  ﾃﾞﾊﾞｲｽｴﾗｰ  *********************************/
char	*msg[] = {
	"環境エラー : 環境設定をし直すか、本プログラムの使用を諦めて下さい♪",
	"ＭＳ−ＤＯＳで使用する場合には、'CDDRV.SYS' と 'CDISC.SYS' のデバイス",
	"ドライバが必要です。"
				} ;
void deverr()
{
	printf("\x1b[31m") ;
	printf("%s\n",msg[0]) ;
	printf("\x1b[33m") ;
	printf("※") ;
	printf("%s\n",msg[1]) ;
	printf("%s\n",msg[2]) ;
	printf("\x1b[m") ;
}

/**************************  ＣＤの演奏をします。 ****************************/
/*
**	<input>		: tocon   - =1(!=0) TOC 情報の取得をする。
**                          =0      TOC 情報の取得はしない。
**              : startno - 演奏開始曲番号
**              : endno   - 演奏終了曲番号
**              : repeat  - リピート回数
**
**	<return>	: = 0 - 正常終了
**				: = 1 - エラー
*/
int CDplay( int tocread, int startno, int endno, unsigned char repeat )
{
	int	errcnt ;
	int	err=FALSE ;

	if ( !repeat ) repeat = 1 ;

	if ( !TOCON || tocread ) {
		errcnt = 0 ;
		do {
			err = cdinfo() ;
			if ( err == DEVERR ) {
				deverr() ;
				exit( 1 ) ;
			}
			CDR_pause( Cddrv ) ;
#if DEBUG
			printf("error(%02d) : -cdinfo- %xH\n",errcnt,err) ;
#endif
			errcnt++ ;
		} while ( err && errcnt<=RETRY ) ;
		if ( errcnt<=RETRY ) {
			TOCON = TRUE ;
		} else {
#if DEBUG
			printf("-cdinfo- error : %xH\n",err) ;
#endif
			printf("\nＣＤがセットされていません！\n") ;
			err = TRUE ;
			goto close ;
		}
	}
	err = 0 ;
#if	DEBUG
	printf("cdtype     : %d\n",Cdtype) ;
	printf("starttrack : %d\n",Sttrack) ;
	printf("endtrack   : %d\n",Endtrack) ;
	for ( err=0; err<Endtrack; err++ ) {
		printf("min-sec-frame(%02d) : %02d-%02d-%02d\n",
				err,Trtime[err].min,Trtime[err].sec,Trtime[err].frame) ;
	} ;
	err = 0 ;
#endif
/*
**	CDDA のないコンパクトディスクには用がないので、プログラム終了！
*/
	if ( Cdtype!=1 && Cdtype!=3 ) {
		printf("\n音楽の入っていないＣＤのため、演奏できません！\n") ;
		err = TRUE ;
		goto close ;
	}

	if ( Endtrack<=0 || Endtrack>99 ) goto close ;
	if ( Endtime.frame<=0 && Endtime.sec<=0 && Endtime.min<=0 ) goto close ;

	errcnt = 0 ;
	usestset( startno ) ;
	useetset( endno ) ;
	printf("REPEAT (%02d)\n",repeat) ;
	do	{										/*  演奏開始			*/
		if ( mtrplay( repeat ) == 0x102 ) CDR_pause( Cddrv ) ;
		mtrplay( repeat ) ;		mphase() ;
		if ( ++errcnt >= RETRY ) {
			printf("\n<cdplay> CD READ ERROR (mtrplay)") ;
			err = TRUE ;
			goto close ;
		}
	} while ( !Status );

close:
	return( err ) ;
}

