/****************************************************************************
DESCRIPTION
    unmute the volume by message to allow a full dsp buffer to have been collected
    which will ensure a smooth ramping of the volume level
*/
void SubConnectedNowUnmuteVolume(DECODER_t * DECODER)
{
    A2dpPluginConnectParams *codecData = (A2dpPluginConnectParams *) DECODER->params;
    
    /* Ensure the volume is set before applying it, it may not yet have become available from the VM app */
    if(DECODER->volume.main.master != DIGITAL_VOLUME_MUTE || DECODER->volume.aux.master != DIGITAL_VOLUME_MUTE)
    {
        /* send the volume message to unmute the audio after a preset delay to allow
           a full dsp buffer to make use of the soft unmute function */
        MAKE_AUDIO_MESSAGE( AUDIO_PLUGIN_SET_GROUP_VOLUME_MSG ) ;
    
        /* create volume message contents */
        memmove(message, &DECODER->volume, sizeof(AUDIO_PLUGIN_SET_GROUP_VOLUME_MSG_T));
        
        /* schedule in the unmute in 100ms*/
        MessageSendLater((TaskData *)DECODER->task, AUDIO_PLUGIN_SET_GROUP_VOLUME_MSG, message , ALLOW_FULL_DSP_BUFFER_DELAY_FOR_SOFT_MUTE) ;
    }
    else
    {
        PRINT(("DECODER: SubConnectedNowUnmuteVolume - vol not set\n" ));
    }
    /* release the lock on changing volume and playing tones */
    codecData->delay_volume_message_sending = FALSE;
    
    PRINT(("DECODER: SubConnectedNowUnmuteVolume\n" ));
}
/****************************************************************************
DESCRIPTION
	handles the internal cvc messages /  messages from the dsp
*/
void CsrA2dpDecoderPluginInternalMessage( A2dpPluginTaskdata *task ,uint16 id , Message message )
{
	switch(id)
	{
        case MESSAGE_FROM_KALIMBA:
		{
			const DSP_REGISTER_T *m = (const DSP_REGISTER_T *) message;
	        PRINT(("DECODER: msg id[%x] a[%x] b[%x] c[%x] d[%x]\n", m->id, m->a, m->b, m->c, m->d));

            switch ( m->id )
			{
              case MUSIC_READY_MSG:
                {
					if (DECODER)
					{
                    	KalimbaSendMessage(MUSIC_LOADPARAMS_MSG, MUSIC_PS_BASE, 0, 0, 0);

                    	/*A2dp is now loaded, signal that tones etc can be scheduled*/
                    	AUDIO_BUSY = NULL ;

                    	PRINT(("DECODER: DECODER_READY \n"));

                     CsrA2dpDecoderPluginSetMode(DECODER->mode, task, 0);

                    	MusicConnectAudio (task, DECODER->stereo);
					}
                }
                break;
			    case MUSIC_CODEC_MSG:
	            {
                    uint16 lOutput_gain_l = m->a;
                    uint16 lOutput_gain_r = m->b;

					if (DECODER)
					{
                    	CodecSetOutputGainNow(DECODER->codec_task, lOutput_gain_l, left_ch);
                    	CodecSetOutputGainNow(DECODER->codec_task, lOutput_gain_r, right_ch);
					}
	            }
                break;
				case KALIMBA_MSG_SOURCE_CLOCK_MISMATCH_RATE:
				{
					MAKE_AUDIO_MESSAGE(AUDIO_PLUGIN_DSP_MSG);
					message->id = KALIMBA_MSG_SOURCE_CLOCK_MISMATCH_RATE;
					message->value = m->a;
					MessageSend(DECODER->app_task, AUDIO_PLUGIN_DSP_MSG, message);
					break;
				}
            }
		}
		break;

        default:
        break ;
	}
}
/****************************************************************************
DESCRIPTION

	messages from the audio library are received here. 
	and converted into function calls to be implemented in the 
	plugin module
*/ 
static void handleAudioMessage ( Task task , MessageId id, Message message ) 	
{
	switch (id)
	{
		case (AUDIO_PLUGIN_CONNECT_MSG ):
		{
			AUDIO_PLUGIN_CONNECT_MSG_T * connect_message = (AUDIO_PLUGIN_CONNECT_MSG_T *)message ;
	
			if (AUDIO_BUSY)
			{ 		/*Queue the connect message until the audio task is available*/
				MAKE_AUDIO_MESSAGE( AUDIO_PLUGIN_CONNECT_MSG ) ; 
				
				message->audio_sink = connect_message->audio_sink ;
				message->codec_task = connect_message->codec_task ;
				message->volume     = connect_message->volume ;
				message->rate		= connect_message->rate;
				message->mode 		= connect_message->mode ;
				message->stereo     = connect_message->stereo ;
				message->params     = connect_message->params ;
				
			    MessageSendConditionally ( task, AUDIO_PLUGIN_CONNECT_MSG , message , (const uint16 *)&AUDIO_BUSY ) ;
			} 
			else
			{		/*connect the audio*/
				CsrFaststreamSourcePluginConnect(   connect_message->audio_sink , 
    									  connect_message->codec_task ,
    									  connect_message->volume , 
    									  connect_message->rate ,
    									  connect_message->stereo ,
    	     							  connect_message->mode   , 
                                          connect_message->params ) ;
			}			
		}	
		break ;
		
		case (AUDIO_PLUGIN_DISCONNECT_MSG ):
		{
			MessageCancelAll ( task , AUDIO_PLUGIN_CONNECT_MSG ) ;
			
			if (AUDIO_BUSY)
			{
				MessageSendConditionally ( task, AUDIO_PLUGIN_DISCONNECT_MSG , 0 ,(const uint16 *)&AUDIO_BUSY ) ;
    		}
			else
			{
				CsrFaststreamSourcePluginDisconnect() ;
			}
		}	
		break ;
		
		case (AUDIO_PLUGIN_SET_MODE_MSG ):
		{
            AUDIO_PLUGIN_SET_MODE_MSG_T * mode_message = (AUDIO_PLUGIN_SET_MODE_MSG_T *)message ;			
			
            if (AUDIO_BUSY)
            {
                MAKE_AUDIO_MESSAGE ( AUDIO_PLUGIN_SET_MODE_MSG) ;
                message->mode   = mode_message->mode ;
                message->params = mode_message->params ;
        
        		MessageSendConditionally ( task, AUDIO_PLUGIN_SET_MODE_MSG , message ,(const uint16 *)&AUDIO_BUSY ) ;    	
            }
            else
            {
                CsrFaststreamSourcePluginSetMode(mode_message->mode , mode_message->params) ;
            }
		}
		break ;
		
		case (AUDIO_PLUGIN_SET_VOLUME_MSG ): 
		{
			AUDIO_PLUGIN_SET_VOLUME_MSG_T * volume_message = (AUDIO_PLUGIN_SET_VOLUME_MSG_T *)message ;			
			
			if (AUDIO_BUSY)
			{
			     MAKE_AUDIO_MESSAGE (AUDIO_PLUGIN_SET_VOLUME_MSG ) ;
			     message->volume = volume_message->volume ;
			     
		         MessageSendConditionally ( task, AUDIO_PLUGIN_SET_VOLUME_MSG , message ,(const uint16 *)&AUDIO_BUSY ) ;  
            }
            else
            {
                CsrFaststreamSourcePluginSetVolume ( volume_message->volume ) ;
            }			
		}		
		break ;
		
		case (AUDIO_PLUGIN_PLAY_TONE_MSG ):
		{
			AUDIO_PLUGIN_PLAY_TONE_MSG_T * tone_message = (AUDIO_PLUGIN_PLAY_TONE_MSG_T *)message ;
			
			if (AUDIO_BUSY) 
			{	
				if ( tone_message->can_queue) /*then re-queue the tone*/
				{				
					MAKE_AUDIO_MESSAGE( AUDIO_PLUGIN_PLAY_TONE_MSG ) ; 
					
					message->tone        = tone_message->tone       ;
					message->can_queue   = tone_message->can_queue  ;
					message->codec_task  = tone_message->codec_task ;
					message->tone_volume = tone_message->tone_volume;
					message->stereo      = tone_message->stereo     ;
	
					PRINT(("SBCDSP: Tone Q\n"));
					
					MessageSendConditionally ( task , AUDIO_PLUGIN_PLAY_TONE_MSG, message ,(const uint16 *)&AUDIO_BUSY ) ;			
				}
			}
			else
			{
				PRINT(("SBCDSP: Tone start\n"));				
				/* TODO - No tone mixing for now */
				/*
				AUDIO_BUSY = TRUE ;					
				CsrFaststreamSourcePluginPlayTone ( tone_message->tone, tone_message->codec_task  , 					  
								        tone_message->tone_volume, tone_message->stereo      ) ;		     				
				*/
			}
							     
		}
		break ;
		
		case (AUDIO_PLUGIN_STOP_TONE_MSG ):
		{
			if (AUDIO_BUSY)
			{
				CsrFaststreamSourcePluginStopTone() ;
			}
		}
		break ;		
		
		default:
		{
		}
		break ;
	}
}
/****************************************************************************
DESCRIPTION

    messages from the audio library are received here. 
    and converted into function calls to be implemented in the 
    plugin module
*/ 
static void handleAudioMessage ( Task task , MessageId id, Message message )     
{
    switch (id)
    {
        case (AUDIO_PLUGIN_VOICE_PROMPTS_INIT_MSG ):
        {
            AUDIO_PLUGIN_VOICE_PROMPTS_INIT_MSG_T * init_message = (AUDIO_PLUGIN_VOICE_PROMPTS_INIT_MSG_T *)message;
            CsrVoicePromptsPluginInit(init_message->no_prompts, init_message->no_languages);
        }
        break;
        
        case (AUDIO_PLUGIN_PLAY_AUDIO_PROMPT_MSG ):
        {
            AUDIO_PLUGIN_PLAY_AUDIO_PROMPT_MSG_T * prompt_message = (AUDIO_PLUGIN_PLAY_AUDIO_PROMPT_MSG_T *)message ;
                           
            /* if the audio is currently busy then queue this audio prompt request, or if the audio plugin is in an 'about to be loaded state', queue until it is
                                     loaded and running */
            if ((IsAudioBusy())||(GetCurrentDspStatus() && (GetCurrentDspStatus() != DSP_RUNNING)))
            {    
                if ( prompt_message->can_queue) 
                {                
                    MAKE_AUDIO_MESSAGE( AUDIO_PLUGIN_PLAY_AUDIO_PROMPT_MSG) ; 
                    memmove(message, prompt_message, sizeof(AUDIO_PLUGIN_PLAY_AUDIO_PROMPT_MSG_T));
                    MessageSendConditionally ( task , AUDIO_PLUGIN_PLAY_AUDIO_PROMPT_MSG, message ,(const uint16 *)AudioBusyPtr() ) ;
                    PRINT(("VP:Queue\n")); 
                }
            }
            else
            {
                CsrVoicePromptsPluginPlayPhrase (prompt_message->id,
                    prompt_message->language, prompt_message->codec_task,
                    prompt_message->ap_volume, prompt_message->features);
                PRINT(("VP:start\n"));
            } 
        }
        break ;
        
        case (AUDIO_PLUGIN_STOP_AUDIO_PROMPT_MSG ):
            CsrVoicePromptsPluginStopPhrase() ;
        break;
        
		case (AUDIO_PLUGIN_PLAY_TONE_MSG ):
		{
			AUDIO_PLUGIN_PLAY_TONE_MSG_T * tone_message = (AUDIO_PLUGIN_PLAY_TONE_MSG_T *)message ;
			
			if (IsAudioBusy()) 
			{	
				if ( tone_message->can_queue) /*then re-queue the tone*/
				{				
					MAKE_AUDIO_MESSAGE( AUDIO_PLUGIN_PLAY_TONE_MSG ) ; 
					
					message->tone        = tone_message->tone       ;
					message->can_queue   = tone_message->can_queue  ;
					message->codec_task  = tone_message->codec_task ;
					message->tone_volume = tone_message->tone_volume;
					message->features    = tone_message->features   ;
	
					PRINT(("VP: tone Q\n"));
					
					MessageSendConditionally ( task , AUDIO_PLUGIN_PLAY_TONE_MSG, message ,(const uint16 *)AudioBusyPtr() ) ;			
				}
			}
			else
			{			
				PRINT(("VP:tone start\n"));

        		CsrVoicePromptsPluginPlayTone (task, tone_message->tone,
                                tone_message->codec_task,
                                tone_message->tone_volume,
                                tone_message->features) ;
			}
							     
		}
		break ;        
        
		case (AUDIO_PLUGIN_STOP_TONE_MSG ):
            CsrVoicePromptsPluginStopPhrase() ;
		break ;		        
        
        default:
            /*other messages do not need to be handled by the voice prompts plugin*/
        break ;
    }
}