/***************************************************************************
 *
 * CRI Middleware SDK
 *
 * Copyright (c) 2005-2006 CRI-MW
 *
 * Appli.   : ADX Tutorial
 * Module   : ADX Tutorial No.1(Playing a single ADX file)
 * File     : adx_t01_simple_play.c
 *
 ***************************************************************************/
/***************************************************************************
 *	DESC. : Playing a single ADX from file.
 *		Music	: File streaming(Stereo)
 *
 *	This program is for ...
 *		PLAYSTATION(R)3 Programmer Tool Runtime Library 082.006 or later
 *		DEH-R10xx
 *
 *	Please set necessary sound file in home directory of logical
 *	consolle server.
 ***************************************************************************/

/***************************************************************************
 *		Include files
 ***************************************************************************/
#include <stdio.h>
#include <string.h>

#include <sdk_version.h>
#include <sys/paths.h>
#include <sysutil/sysutil_sysparam.h>
#include <cell/audio.h>
#include <cell/mixer.h>

#include <cri_mw.h>

/***************************************************************************
 *		Constants
 ***************************************************************************/
/* Mount point for libfs */
#define MOUNT_POINT	SYS_APP_HOME "/"

/* Configurations for SurMixer */
#define SUR_MIXER_PRIORITY		(400)
#define SUR_MIXER_CHSTRIPS1		(0)
#define SUR_MIXER_CHSTRIPS2		(0)
#define SUR_MIXER_CHSTRIPS6		(0)
#define SUR_MIXER_CHSTRIPS8		(0)

/* Using headphone */
#define	USE_HEADPHONE	(1)

/* Configurations for CRI's middlewares ========================= */
/* The number of output channels */
#define NUM_OUTPUT_CHANNELS	(2)
/* The maximum number of voices("voice" means one sound) */
#define NUM_MAX_VOICES		(1)
/* ============================================================== */

/***************************************************************************
 *		Macros
 ***************************************************************************/
#if !defined UNUSED
#define UNUSED(arg)		{ if ((arg) == (arg)) {} }
#endif

/***************************************************************************
 *      Data Type Declarations
 ***************************************************************************/

/***************************************************************************
 *		Variable Definitions
 ***************************************************************************/

/***************************************************************************
 *		Function Declarations
 ***************************************************************************/
// Initializing
static void initialize();
// Finalizing
static void finalize();

/* Initialize Video */
static Sint32 initializeVideo();
/* Finalize Video */
static Sint32 finalizeVideo();
/* Initialize Audio */
static Sint32 initializeAudio();
/* Finalize Audio */
static Sint32 finalizeAudio();

/* Sound notification callback for SurMixer */
static Sint32 soundNotifyCallback(void *arg, Uint32 counter, Uint32 num_samples);

/***************************************************************************
 *		Function Definitions
 ***************************************************************************/
int main(int argc, char *argv[])
{
	ADXT				adxt;
	Sint32				wksize, max_ch, max_stm, max_sfreq;
	Uint8				*work;
	Adxps3SoundConfig	config;
	CellAANHandle		sur_mixer_handle;

	initialize();

	// Get SurMixer handle
	cellSurMixerGetAANHandle(&sur_mixer_handle);
	// Sound system configuration
	memset(&config, 0, sizeof(config));
	config.mixer_handle			= sur_mixer_handle;
	config.num_output_channels	= NUM_OUTPUT_CHANNELS;
	config.num_max_voices		= NUM_MAX_VOICES;
	config.work_size			= ADXPS3_CalcSoundWorkSize(&config);
	config.work					= malloc(config.work_size);

	// Set up middleware sound system
	ADXPS3_SetupSound(&config);
	// Set up middleware file streaming I/O
	ADXPS3_SetupPs3Fs(NULL);
	// Set up middleware framework
	ADXM_SetupFramework(ADXM_FRAMEWORK_DEFAULT, NULL);

	// ATTN: This must be called after ADXPS3_SetupSound().
	// Start SurMixer
	cellSurMixerStart();


	// Initialize ADX
	ADXT_Init();

	// Create ADXT Handle
	max_ch = 2;
	max_stm = 1;
	max_sfreq = 48000;
	wksize = ADXT_CALC_WORK(max_ch, ADXT_PLY_STM, max_stm, max_sfreq);
	work = (Uint8 *)malloc(wksize);
	adxt = ADXT_Create(max_ch, work, wksize);

	// Start playing ADX file
	ADXT_StartFname(adxt, MOUNT_POINT"music48a.adx");

	// Loop for PLAYEND of ADXT
	for (;;) {
		// Wait for Vsync
		ADXM_WaitVsync();
		// Middleware server function
		ADXM_ExecMain();
		
		// Checking status
		if (ADXT_GetStat(adxt) == ADXT_STAT_PLAYEND) {
			break;
		}
	}
	
	// Destroy ADXT handle
	ADXT_Destroy(adxt);

	// Finalize ADX Library
	ADXT_Finish();


	// Shutdown middleware framework
	ADXM_ShutdownFramework();
	// Shutdown middleware streaming file I/O
	ADXPS3_ShutdownPs3Fs();

	/* ### NOTE ###														*/
	/* When you're going to shutdown the ADX sound system, pause the	*/
	/* SurMixer to stop the callback.									*/
	// Pause SurMixer immediatelly
	cellSurMixerPause(CELL_SURMIXER_CONT_PAUSE_ON_IMMEDIATE);
	// Shutdown middleware sound system
	ADXPS3_ShutdownSound();

	finalize();

	return 0;
}

// Initializing
static void initialize()
{
	Sint32 err;

	err = cellSysutilInit();
	if (err < 0) {
		printf("cellSysutilInit() error : %#8x\n", err);
		return;
	}

	// Initialize Video
	initializeVideo();

	// Initialize Audio
	initializeAudio();
}

// Finalizing
static void finalize()
{
	// Finalize Audio
	finalizeAudio();

	// Finalize Video
	finalizeVideo();
}



/* Initialize Video */
static Sint32 initializeVideo()
{
	Sint32 err;
	CellVideoOutConfiguration v_config;
	
	/* video configuration */
	memset(&v_config, 0, sizeof(v_config));
	v_config.resolutionId	= CELL_VIDEO_RESOLUTION_720;
	v_config.format			= CELL_VIDEO_BUFFER_COLOR_FORMAT_X8R8G8B8;
	v_config.pitch			= 1280 * 4;
	err = cellVideoOutConfigure(CELL_VIDEO_OUT_PRIMARY, &v_config, NULL, 0);
	if (err < 0) {
		printf("cellVideoOutConfigure() error : %#8x\n", err);
		return err;
	}

	return 0;
}

/* Finalize Video */
static Sint32 finalizeVideo()
{
	return 0;
}

/* Initialize Audio */
static Sint32 initializeAudio()
{
	Sint32 err;
	CellAudioOutConfiguration a_config;
	CellSurMixerConfig sur_mixer_config;

	/* audio configuration */
	memset(&a_config, 0, sizeof(a_config));
	a_config.channel	= 2;
	a_config.downMixer	= CELL_AUDIO_DOWNMIXER_NONE;
	err = cellAudioOutConfigure(CELL_AUDIO_OUT_PRIMARY, &a_config, NULL, 0);
	if (err < 0) {
		printf("cellAudioOutConfigure() error : %#8x\n", err);
		return err;
	}

	// Initialize AudioServer
	err = cellAudioInit();
	if (err < 0){
		printf("cellAudioInit() error : %#8x\n", err);
		return err;
	}

	/* ### NOTE ###															*/
	/* The ADX sound system uses the CellSurMixer(libmixer).				*/
	/* You have to configure and create the CellSurMixer.					*/

	/* SurMixer configuration */
	memset(&sur_mixer_config, 0, sizeof(sur_mixer_config));
	sur_mixer_config.priority	= SUR_MIXER_PRIORITY;
	sur_mixer_config.chStrips1	= SUR_MIXER_CHSTRIPS1;
	sur_mixer_config.chStrips2	= SUR_MIXER_CHSTRIPS2;
	sur_mixer_config.chStrips6	= SUR_MIXER_CHSTRIPS6;
	sur_mixer_config.chStrips8	= SUR_MIXER_CHSTRIPS8;

	/* Create SurMixer */
	err = cellSurMixerCreate(&sur_mixer_config);
	if (err < 0) {
		printf("cellSurMixerCreate() error : %d\n", err);
		return err;
	}

	/* ### NOTE ###															*/
	/* If application does not input audio data to SurMixer, you can set	*/
	/* ADXPS3_SoundNotifyCallback() to SurMixer directly.					*/
	/* Set notify callback */
	err = cellSurMixerSetNotifyCallback(soundNotifyCallback, NULL);
	if (err < 0) {
		printf("cellSurMixerSetNotifyCallback() error : %#8x\n", err);
		return err;
	}

#if (USE_HEADPHONE == 1)
	printf("Set TotalLevel for Headphone\n");
	/* Set total level for headphone */
	err = cellSurMixerSetParameter(CELL_SURMIXER_PARAM_TOTALLEVEL, -24.0);
	if (err < 0) {
		printf("cellSurMixerSetParameter() error : %#8x\n", err);
		return err;
	}
#endif

	return 0;
}

/* Finalize Audio */
static Sint32 finalizeAudio()
{
	Sint32 err;

	err = cellSurMixerFinalize();
	if (err < 0){
		printf("cellSurMixerFinalize() error : %#8x\n", err);
		return err;
	}

	// Finalize AudioServer
	err = cellAudioQuit();
	if (err < 0){
		printf("cellAudioQuit() error : %#8x\n", err);
		return err;
	}

	return 0;
}

/* Sound notification callback for SurMixer */
static Sint32 soundNotifyCallback(void *arg, Uint32 counter, Uint32 num_samples)
{
	Sint32 ret;
	
	/* ### NOTE ###															*/
	/* If application needs own sound output, input sound data to SurMixer	*/
	/* here.																*/
	/* Application sound output				*/
	/*					:					*/
	/*					:					*/

	/* Call Sound notification callback of ADX */
	ret = ADXPS3_SoundNotifyCallback(arg, counter, num_samples);

	return ret;
}

/* --- end of file --- */
