/*****************************************************************************\

  File Name: mgr_player.c

  Description: This module contains player manager specific functions.

  Copyright(c) 2007 Analog Devices Incorporated. All Rights Reserved.

  Revision History:


\*****************************************************************************/

/*****************************************************************************\

  Includes:

\*****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <drivers/adi_dev.h>			// Device manager includes
#include <SDK-ezkitutilities.h>
#include "devicecontrol.h"
#include "mediaplayer.h"
#include <adac_buffer.h>
#include <WAV_codec.h>
#include <adi_mp3_dec.h>
#include <adi_heaacv2_decoder.h>
#include <jpeg_decode.h>
#include <BitmapViewer.h>

/*****************************************************************************\

  Defines:

\*****************************************************************************/

/*****************************************************************************\

  Declarations:

\*****************************************************************************/
semaphore_t DecodeEvents[] =
{     
    {(void *)0,(void *)0},
    {(void *)0,(void *)0}

};


MPPMESSAGE	CmdStatusToApp;

static char file_path[MAX_PATH_NAME_LEN];


/* stack for thread_mgr_player */
section("sdram0_bank2_stack") static OS_STK stack[THRD_STACKSIZE * sizeof(OS_STK)];
/* stack for thread_audio_decode */
section("sdram0_bank2_stack") static OS_STK stack1[THRD_STACKSIZE * sizeof(OS_STK)];
OS_EVENT *audio_decode_Q;
void* audio_decode_arr[SZ_MSGQ_APP_CMD];

/* stack for thread_video_decode */
section("sdram0_bank2_stack") static OS_STK stack2[THRD_STACKSIZE * sizeof(OS_STK)];
OS_EVENT *video_decode_Q;
void* video_decode_arr[SZ_MSGQ_APP_CMD];

/* FIFO Block - to hold 16-bit PCM samples */
section("mpp_nocache") volatile short AudioFifoBlock[PCM_FIFO_BUFFER_SIZE * NUM_PCM_FIFO_BUFFERS];

/*****************************************************************************\

  Externs:

\*****************************************************************************/
extern u8 	YUVBuf422		[800 * 608 *2 *4];  

/* queue to hold app-ply commands */
extern OS_EVENT *mgr_player_Q;	
extern OS_EVENT *mgr_application_Q;
extern OS_EVENT *mgr_display_Q;

extern semaphore_t mpEvents[];

/* Empty void* array to hold Q messages */
extern void* mgr_player_arr[SZ_MSGQ_APP_CMD]; 

extern u8 PingFrame[480*272*3];
/*****************************************************************************

Function prototypes

*****************************************************************************/ 
void init_mgr_player(void);	
void launch_thread_mgr_player(void);
void thread_mgr_player(void *pEvent);
void thread_audio_decode(void *pEvent);
void thread_video_decode(void *pEvent);

/*********************************************************************

	Function:	init_mgr_player																			
	
 	Parameters:	None 
																		
 	Return:		None														
																			
 	Description:	Initialises the player manager
*********************************************************************/
void init_mgr_player(void)
{
	/* launch a task to communicate from/to APP-manager */	
    launch_thread_mgr_player();	
	
	
}	

/*********************************************************************

	Function:	launch_thread_mgr_player																			
	
 	Parameters:	None 
																		
 	Return:		None														
																			
 	Description:	Launches a task thread which handles all APP commands
*********************************************************************/
section ("sdram0_bank2_thread")
void launch_thread_mgr_player(void) 
{
	int Result;
	INT32U i;

	/*------------ create a task to handle APP commands ---------------*/
	/* Create app-keypad message Queue */
	mgr_player_Q = OSQCreate(mgr_player_arr, SZ_MSGQ_APP_CMD);
	mpEvents[1].sem = mgr_player_Q;
	
	
	Result = OSTaskCreateExt(thread_mgr_player, 
						(void *)&mpEvents[1], 
						&stack[THRD_STACKSIZE -1], 
						THRD_PRIORITY_MANAGER_PLAYER, 
						MANAGER_PLAYER_ID, 
						&stack[0], 
						THRD_STACKSIZE , 
						(void *)0, 
						OS_TASK_OPT_STK_CHK );
	if(Result && APP_TRACE_LEVEL)					
	{					
    	APP_TRACE("OSTaskCreateExt create thread_mgr_player error%d\n",Result); /* wait for help */
    			ezErrorCheck(1);

	}	
   
	/*------------ create a task to decode audio file---------------*/

    /* Create playAudio message Queue */
	audio_decode_Q = OSQCreate(audio_decode_arr, SZ_MSGQ_APP_CMD);
	DecodeEvents[0].sem = audio_decode_Q;
	

	
	Result = OSTaskCreateExt(thread_audio_decode, 
						(void *)&DecodeEvents[0], 
						&stack1[THRD_STACKSIZE -1], 
						THRD_PRIORITY_MANAGER_AUDIO, 
						MANAGER_AUDIO_ID, 
						&stack1[0], 
						THRD_STACKSIZE , 
						(void *)0, 
						OS_TASK_OPT_STK_CHK );
	if(Result && APP_TRACE_LEVEL)					
	{					
    	APP_TRACE("OSTaskCreateExt thread_audio_decode error %d\n",Result); /* wait for help */
    	  ezErrorCheck(1);

	}
	
	
	/*------------ create a task to decode video file---------------*/

    /* Create video decode message Queue */
	video_decode_Q = OSQCreate(video_decode_arr, SZ_MSGQ_APP_CMD);
	DecodeEvents[1].sem = video_decode_Q;
	

	
	Result = OSTaskCreateExt(thread_video_decode, 
						(void *)&DecodeEvents[1], 
						&stack2[THRD_STACKSIZE -1], 
						THRD_PRIORITY_MANAGER_VIDEO, 
						MANAGER_VIDEO_ID, 
						&stack2[0], 
						THRD_STACKSIZE , 
						(void *)0, 
						OS_TASK_OPT_STK_CHK );
	if(Result && APP_TRACE_LEVEL)					
	{					
    	APP_TRACE("OSTaskCreateExt thread_video_decode error %d\n",Result); /* wait for help */
    	  ezErrorCheck(1);

	}	
	

		
 
}// end of launch_threads


/*********************************************************************

	Function:	thread_mgr_player																			
	
 	Parameters:	None 
																		
 	Return:		None														
																			
 	Description: handles all APP commands
 					
*********************************************************************/
section ("sdram0_bank2_thread")
void thread_mgr_player(void *pEvent)
{
	INT8U err;
	MPPMESSAGE	*pMessage;
    u32 slen ;
	MPPMESSAGE	MessageToDecoder;
	MPPMESSAGE	MessageToDisplay;
	u32 Result;
	bool ValidAudioFile = FALSE;
	bool ValidVideoFile = FALSE;



	semaphore_t *p;

	p = (semaphore_t *)pEvent;
	
	OS_EVENT *queue = p->sem;

    while(1)
	{
		
	    // pend on message queue
	    pMessage = (MPPMESSAGE *) OSQPend (queue, 0, &err);
		if (err && APP_TRACE_LEVEL)
		{					
    		APP_TRACE("thread_mgr_player OSQPend error %d\n",err); /* wait for help */
    		ezErrorCheck(1);
		}	

		switch(pMessage->uMID)
		{
				case MSGID_PLAYER_STOP:
						/* message to mgr_display to update status field in lcd screen */
						MessageToDisplay.uMID = MSGID_LCD_STATUS;
						MessageToDisplay.Param1 = STATE_IDLE;
						err = OSQPost(mgr_display_Q, &MessageToDisplay);
						
						/* message to mgr_display to clear all File Tag Information */
    					MessageToDisplay.uMID = MSGID_LCD_TAG;
	    				MessageToDisplay.Param1 = TAG_CLEAR;
    					MessageToDisplay.Param2 = NULL;
	    				OSQPost(mgr_display_Q, &MessageToDisplay);
					
					break;
				
				case MSGID_PLAYER_PAUSE:
					/* post a message to mgr_display to update lcd screen */
					MessageToDisplay.uMID = MSGID_LCD_STATUS;
					MessageToDisplay.Param1 = STATE_PAUSE;
					err = OSQPost(mgr_display_Q, &MessageToDisplay);
					if (err && APP_TRACE_LEVEL)
					{
    					APP_TRACE("thread_mgr_filesystem OSQPost failed %d\n",err);
						ezErrorCheck(1);/*wait for help*/
					}

					break;
				
				
				case MSGID_PLAYER_RESUME:
					/* post a message to mgr_display to update lcd screen */
					MessageToDisplay.uMID = MSGID_LCD_STATUS;
					MessageToDisplay.Param1 = STATE_PLAY;
					err = OSQPost(mgr_display_Q, &MessageToDisplay);
					if (err && APP_TRACE_LEVEL)
					{
    					APP_TRACE("thread_mgr_filesystem OSQPost failed %d\n",err);
						ezErrorCheck(1);/*wait for help*/
					}
					break;
				
				case MSGID_PLAYER_PLAY:
					/* get the file path from the message */
					strcpy(file_path, (char*)pMessage->Param2);
					slen = strlen(file_path);
					MessageToDecoder.Param2 = file_path;
					
					ValidAudioFile = FALSE;
    				ValidVideoFile = FALSE;

					
    				/* IF (file extension is aac or mp4 or adif, call AAC decoder) */
    				if (!strncmp(".mp4",&file_path[slen-4],4) || !strncmp(".MP4",&file_path[slen-4],4) ||
    					!strncmp(".aac",&file_path[slen-4],4) || !strncmp(".AAC",&file_path[slen-4],4) ||
    					!strncmp(".m4a",&file_path[slen-4],4) || !strncmp(".M4A",&file_path[slen-4],4) ||
						!strncmp(".adif",&file_path[slen-5],5) || !strncmp(".ADIF",&file_path[slen-5],5))
    				{
    					MessageToDecoder.Param1 = AAC_TYPE;
    					ValidAudioFile = TRUE;
    				}	  	
    				/* IF (file extension is MP3, call MP3 decoder) */
    				else if (!strncmp(".mp3",&file_path[slen-4],4) || !strncmp(".MP3",&file_path[slen-4],4) )
    				{
    					MessageToDecoder.Param1 = MP3_TYPE;
    					ValidAudioFile = TRUE;

    				}
     				else if (!strncmp(".wav",&file_path[slen-4],4) || !strncmp(".WAV",&file_path[slen-4],4)|| !strncmp(".ADIF",&file_path[slen-5],5) || !strncmp(".adif",&file_path[slen-5],5))
   					{
    					MessageToDecoder.Param1 = WAV_TYPE;
    					ValidAudioFile = TRUE;

    				}
    				/* IF (file extension is JPG, call JPEG decoder) */
     				else if (!strncmp(".jpg",&file_path[slen-4],4) || !strncmp(".JPG",&file_path[slen-4],4))
   					{
    					MessageToDecoder.Param1 = JPG_TYPE;
    					ValidVideoFile = TRUE;
    				}
    				
    				else if (!strncmp(".raw",&file_path[slen-4],4) || !strncmp(".RAW",&file_path[slen-4],4))
   					{
    					MessageToDecoder.Param1 = RAW_TYPE;
    					ValidVideoFile = TRUE;
   					}	
   					else if (!strncmp(".bmp",&file_path[slen-4],4) || !strncmp(".BMP",&file_path[slen-4],4))
   					{
    					MessageToDecoder.Param1 = BMP_TYPE;
    					ValidVideoFile = TRUE;
   					}	
    				else
    				{
    					ValidAudioFile = FALSE;
    					ValidVideoFile = FALSE;
    				}
    				
    				if (ValidAudioFile)
    				{
     					/* post a message to thread_audio_decode to decode audio file */
     					MessageToDecoder.uMID = MSGID_START_DECODE_AUDIO;
						err = OSQPost(audio_decode_Q, &MessageToDecoder);
						
						/* post a message to mgr_display to update status field in lcd screen	*/
						MessageToDisplay.uMID = MSGID_LCD_STATUS;
						MessageToDisplay.Param1 = STATE_PLAY;
						err = OSQPost(mgr_display_Q, &MessageToDisplay);
						
    				}
    				else if (ValidVideoFile)
    				{
     					/* post a message to thread_video_decode to decode video file */
     					MessageToDecoder.uMID = MSGID_START_DECODE_VIDEO;
						err = OSQPost(video_decode_Q, &MessageToDecoder);
						
    				}
  	
    				
					break;
				
				/* message to increase volume */
				case MSGID_VOLUME_UP:
				
					AdjustCodecVolume(MSGID_VOLUME_UP);
				
					break;

				/* volume up command */
				case MSGID_VOLUME_DN:
				
					AdjustCodecVolume(MSGID_VOLUME_DN);


					break;

				default:
					break;
			
		}
		
		if(err && APP_TRACE_LEVEL)
		{					
    		APP_TRACE("thread_mgr_player OSQPost error %d\n",err); /* wait for help */
    		    		ezErrorCheck(1);

		}	

	}	
}

/*********************************************************************

	Function:	thread_audio_decode																			
	
 	Parameters:	None 
																		
 	Return:		None														
																			
 	Description: decode audio file
 					
*********************************************************************/
section ("sdram0_bank2_thread")
void thread_audio_decode(void *pEvent)
{
	u32 Result = ADI_DEV_RESULT_SUCCESS;
	INT8U err;
	MPPMESSAGE	*pMessage, MessageToDisplay;
	semaphore_t *p;

	p = (semaphore_t *)pEvent;
	
	OS_EVENT *queue = p->sem;

    while(1)
	{
		
	    // pend on message queue
	    pMessage = (MPPMESSAGE *) OSQPend (queue, 0, &err);
		if (err && APP_TRACE_LEVEL)
		{					
    		APP_TRACE("thread_audio_decode OSQPend error %d\n",err); /* wait for help */
    		ezErrorCheck(1);
		}	

		switch(pMessage->uMID)
		{
				case MSGID_START_DECODE_AUDIO:

    				/* Initialise FIFO Block */
    				usr_init((void*)AudioFifoBlock, PCM_FIFO_BUFFER_SIZE, NUM_PCM_FIFO_BUFFERS);
				
    				ClearOutboundBuffer();
    			
   					StopButton = FALSE;
   				
   					PauseButton = FALSE;
   					
   					/* send command status to mgr_application */
					CmdStatusToApp.uMID = MSGID_CMD_STATUS;
					CmdStatusToApp.Param1 = MSGID_START_DECODE_AUDIO;
					err = OSQPost(mgr_application_Q, &CmdStatusToApp);
				
				
					/* post a message to mgr_display to update lcd screen */
					MessageToDisplay.uMID = MSGID_LCD_STATUS;
					MessageToDisplay.Param1 = STATE_PLAY;
					err = OSQPost(mgr_display_Q, &MessageToDisplay);
					
					/* open and configure the audio codec */
					
					/* submit Outbound audio buffers */
    				if ((Result = init_codec()) != ADI_DEV_RESULT_SUCCESS)
    				{
    					printf("Init BF52xC1 codec failed , Error Code: 0x%08X\n",Result);
    				}					
 				    

   					switch(pMessage->Param1)
					{
						case MP3_TYPE:
							MP3_Decode_File(file_path);
							break;

						case AAC_TYPE:
							AAC_Decode(file_path);
							break;
					
						case WAV_TYPE:
							WAV_Decode(file_path);	
							break;
        					
					
						default:
							break;

					}
					
					/* finish with the codec */
					close_codec();

				
   					/* decoding completed send command status to mgr_application */
					CmdStatusToApp.uMID = MSGID_CMD_STATUS;
					CmdStatusToApp.Param1 = MSGID_STOP_DECODE;
					err = OSQPost(mgr_application_Q, &CmdStatusToApp);

						
						/* message to mgr_display to update status field in lcd screen */
						MessageToDisplay.uMID = MSGID_LCD_STATUS;
						MessageToDisplay.Param1 = STATE_IDLE;
						err = OSQPost(mgr_display_Q, &MessageToDisplay);
						
						/* message to mgr_display to clear all File Tag Information */
    					MessageToDisplay.uMID = MSGID_LCD_TAG;
	    				MessageToDisplay.Param1 = TAG_CLEAR;
    					MessageToDisplay.Param2 = NULL;
	    				OSQPost(mgr_display_Q, &MessageToDisplay);

					break;
				

				default:
					break;
			
		}
		if (err && APP_TRACE_LEVEL)
		{
    		APP_TRACE("thread_audio_decode OSQPost failed %d\n",err);
			ezErrorCheck(1);/*wait for help*/
		}	
	}	
}



/*********************************************************************

	Function:	thread_video_decode																			
	
 	Parameters:	None 
																		
 	Return:		None														
																			
 	Description: decode video file
 					
*********************************************************************/
section ("sdram0_bank2_thread")
void thread_video_decode(void *pEvent)
{
	INT8U err;
	MPPMESSAGE	*pMessage, MessageToDisplay;
	semaphore_t *p;
	int Result,i;
		
	p = (semaphore_t *)pEvent;
	
	OS_EVENT *queue = p->sem;
	
	Result = 0;
	
	u8 *pLCDBuffer = PingFrame;

	
    while(1)
	{
		
	    // pend on message queue
	    pMessage = (MPPMESSAGE *) OSQPend (queue, 0, &err);
		if (err && APP_TRACE_LEVEL)
		{					
    		APP_TRACE("thread_video_decode OSQPend error %d\n",err); /* wait for help */
    		ezErrorCheck(1);
		}	

		switch(pMessage->uMID)
		{
				case MSGID_START_DECODE_VIDEO:

    				/* send command status to mgr_application */
					CmdStatusToApp.uMID = MSGID_CMD_STATUS;
					CmdStatusToApp.Param1 = MSGID_START_DECODE_VIDEO;
					err = OSQPost(mgr_application_Q, &CmdStatusToApp);
 					
					
   					switch(pMessage->Param1)
					{
        					
        				case JPG_TYPE:
        					/* decode JPEG file and convert the decoded data into YUV422 format*/	
        					Result = JPEG_decode(file_path);
        					if ( Result != 0);/* cancel the video decoding */
        					{
        						if (Result && APP_TRACE_LEVEL)
								{
    								APP_TRACE("JPEG_decode failed %x\n",Result);
									//ezErrorCheck(1);/*wait for help*/
								}
							
								/* inform mgr_application */
								CmdStatusToApp.uMID = MSGID_CMD_STATUS;
								CmdStatusToApp.Param1 = MSGID_STOP_DECODE;
								err = OSQPost(mgr_application_Q, &CmdStatusToApp);
	
        					}
#if defined(__ADSP_MOAB__)        					
        					init_pixel_compositor();
#endif

#if defined(__ADSP_KOOKABURRA__) 

    						CmdStatusToApp.uMID = MSGID_PIXEL_DONE;
							OSQPost(video_decode_Q, &CmdStatusToApp);
#endif


        					break;
        				
        				case RAW_TYPE:
        						DisplayRAW(file_path, pLCDBuffer);
        						/* inform mgr_application */
								CmdStatusToApp.uMID = MSGID_CMD_STATUS;
								CmdStatusToApp.Param1 = MSGID_STOP_DECODE;
								err = OSQPost(mgr_application_Q, &CmdStatusToApp);
								

        					break;
        					
        				case BMP_TYPE:
        						DisplayBitmap(file_path, pLCDBuffer);
        						/* inform mgr_application */
								CmdStatusToApp.uMID = MSGID_CMD_STATUS;
								CmdStatusToApp.Param1 = MSGID_STOP_DECODE;
								err = OSQPost(mgr_application_Q, &CmdStatusToApp);
								

        					break;	
        				
        				default:
							break;

					}
				
					

				break;
				
				case MSGID_PIXEL_DONE:
#if defined(__ADSP_MOAB__)				
					close_pixel_compositor();
#endif					
					/* inform mgr_application */
					CmdStatusToApp.uMID = MSGID_CMD_STATUS;
					CmdStatusToApp.Param1 = MSGID_STOP_DECODE;
					err = OSQPost(mgr_application_Q, &CmdStatusToApp);

					break;

				default:
					break;
			
		}
		if (err && APP_TRACE_LEVEL)
		{
    		APP_TRACE("thread_video_decode OSQPost failed %d\n",err);
			ezErrorCheck(1);/*wait for help*/
		}	
	}	
}



