/****************************************************************************
NAME 
    a2dpStreamStartDsp

DESCRIPTION
    To load the corresponding DSP kap file for the selected audio plugin, and set 
    the encoder mode.
    
    As the same dsp kap file is used for both USB source and Analogue source, it is 
    better to load the kap file in application instead of plugin library.
 
*/
void a2dpStreamStartDsp(bool isA2DPstreaming)
{    
#ifdef KAL_MSG
    uint16 codec_type = CodecSbc;
    FILE_INDEX index  = FILE_NONE;
    
    DEBUG_A2DP(("a2dpStreamStartDsp %d\n",isA2DPstreaming));

    /* Power off the kalimba first before load the Kap file again */
    KalimbaPowerOff() ;
     
    /* This will be changed if one kap file supports both usb and analogue source types */
    if (isA2DPstreaming)
    {
        Task audio_plugin = initA2dpPlugin(the_app->a2dp_active_seid);
    
        the_app->a2dp_audio_plugin = audio_plugin;
    
        /* Select the corresponding kap file */
        if ( (audio_plugin == (TaskData *)&csr_sbc_encoder_plugin) )
        {
            index = FileFind(FILE_ROOT, sbc_encoder, sizeof(sbc_encoder)-1); 
            codec_type = CodecSbc;
        }
    }
    else
    {    
        /* we should load the source type, and can not set as the default type: SourceUsb*/
        the_app->aghfp_audio_plugin  = initScoPlugin();
        
        /* Select the corresponding kap file */
        index = FileFind(FILE_ROOT, sbc_encoder, sizeof(sbc_encoder)-1);
    }

    /* Load the DSP Kap file */
    if (index == FILE_NONE)
        Panic();
    if (!KalimbaLoad(index))
        Panic();    

    DEBUG_A2DP(("KalimbaLoad %s\n",sbc_encoder));
    
    /* Register the Kalimba message */
    MessageKalimbaTask(&the_app->task);
    
    /* send the codec type to kalimba, this is necessary as codecs share kap files */
    if (codec_type != CodecMp3) 
    {
        if (!KalimbaSendMessage(KALIMBA_CODEC_TYPE_MESSAGE, codec_type,0,0,0))
        {
            Panic();
        }
    }
#else
    DEBUG_A2DP(("a2dpStreamStartDsp %d\n",isA2DPstreaming));
#endif	
}
void CsrSubwooferPluginConnect(Sink audio_sink, Task codec_task, Task app_task, subwooferPluginConnectParams * params)
{
    FILE_INDEX index;
    
    /* Update the current DSP status */
    SetCurrentDspStatus(DSP_LOADING);
    
    /* Give Kalimba the plugin task so it knows where to send messages */
    (void) MessageCancelAll( (TaskData*)&csr_subwoofer_plugin, MESSAGE_FROM_KALIMBA);
    MessageKalimbaTask( (TaskData*)&csr_subwoofer_plugin );
    
    /* Load the Subwofoer DSP application - Panic if it could not be loaded */
    index = PanicFalse( FileFind(FILE_ROOT, kal, sizeof(kal) - 1) );
    PanicFalse( KalimbaLoad(index) );
    
    /* update current DSP status */
    SetCurrentDspStatus(DSP_LOADED_IDLE);
    
    /* Allocate memory to store the plugin data */
    plugin_data = (subwooferPluginData*)PanicUnlessMalloc(sizeof(subwooferPluginData));
    
    /* Initialise the plugin data based on parameters supplied by the application */
    plugin_data->audio_source           = StreamSourceFromSink(audio_sink);
    plugin_data->swat_system_volume_db  = params->swat_system_volume_db;
    plugin_data->swat_trim_gain_db      = params->swat_trim_gain_db;
    plugin_data->adc_volume_index       = params->adc_volume;
    plugin_data->input                  = params->input;
    plugin_data->output                 = params->output;
    plugin_data->sample_rate            = params->sample_rate;
    plugin_data->adc_sample_rate        = params->adc_sample_rate;
    plugin_data->codec_task             = codec_task;
    plugin_data->app_task               = app_task;
    plugin_data->dsp_set_sample_rate    = 0; /* set later in response to AUDIO_PLUGIN_SET_MODE_MSG */
    
    /* Zero the codecs output gain */
    CodecSetOutputGainNow(plugin_data->codec_task, 0, left_and_right_ch);
    CodecSetInputGainNow(plugin_data->codec_task, 0, left_and_right_ch);
    
    
    /* If using the ADC, set the ADC source */
    if (plugin_data->input == SUBWOOFER_INPUT_ADC)
    {
        /* Get the ADC source */
        plugin_data->audio_source = StreamAudioSource(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A);
    }
    
    
    /* Disconnect the source in case it's currently being disposed */
    StreamDisconnect(StreamSourceFromSink(audio_sink), 0);
    
    PRINT(("[SW_PLUGIN] : CsrSubwooferPluginConnect - complete\n"));
}
void CsrSubwooferPluginDisconnect(void)
{
    /* Disconnect the appropriate input to Kalimba */
    if (plugin_data->input == SUBWOOFER_INPUT_ADC)
    {
        PRINT(("[SW_PLUGIN : Disconnect ADC to Kalimba\n"));
        StreamDisconnect(plugin_data->audio_source, StreamKalimbaSink(DSP_INPUT_PORT_ADC));
    }
    else if (plugin_data->input == SUBWOOFER_INPUT_ESCO)
    {
        PRINT(("[SW_PLUGIN] Disconnect eSCO to Kalimba\n"));
        StreamDisconnect(plugin_data->audio_source, StreamKalimbaSink(DSP_INPUT_PORT_ESCO));
        StreamConnectDispose(plugin_data->audio_source);
    }
    else if (plugin_data->input == SUBWOOFER_INPUT_L2CAP)
    {
        PRINT(("[SW_PLUGIN] Disconnect L2CAP to Kalimba\n"));
        StreamDisconnect(plugin_data->audio_source, StreamKalimbaSink(DSP_INPUT_PORT_L2CAP));
        StreamConnectDispose(plugin_data->audio_source);
    }
    
    /* Disconnect the appropriate output from Kalimba */
    if (plugin_data->output == SUBWOOFER_OUTPUT_DAC)
    {
        PRINT(("[SW_PLUGIN] Disconnect Kalimba to DAC\n"));
        StreamDisconnect(StreamKalimbaSource(DSP_OUTPUT_PORT_DAC), plugin_data->codec_sink);
    }
    else if (plugin_data->output == SUBWOOFER_OUTPUT_I2S)
    {
        PRINT(("[SW_PLUGIN] Disconnect Kalimba to I2S\n"));
        CsrI2SAudioOutputDisconnect(TRUE);                                 
    }
    
    /* dispose of any remaining messages in the queue */
    (void) MessageCancelAll( (TaskData*)&csr_subwoofer_plugin, MESSAGE_FROM_KALIMBA);
    MessageKalimbaTask( NULL );
   
    /* Everything has been disconnected so power down Kalimba */
    KalimbaPowerOff();
    
    /* reset flags */
    SetAudioInUse(FALSE);
    SetCurrentDspStatus(DSP_NOT_LOADED);

    /* Free the memory allocated to use for the plugin as it's no longer valid */
    free(plugin_data);
    plugin_data = NULL;
}
/****************************************************************************
DESCRIPTION
	This function connects a synchronous audio stream to the pcm subsystem
*/
void CsrA2dpDecoderPluginConnect( A2dpPluginTaskdata *task, Sink audio_sink , Task codec_task , uint16 volume , uint32 rate , bool stereo , AUDIO_MODE_T mode , const void * params , Task app_task )
{
	FILE_INDEX index = FILE_NONE;
	char* kap_file = NULL ;

	/* Only need to read the PS Key value once */
    if (!pskey_read)
    {
        if (PsFullRetrieve(PSKEY_MAX_CLOCK_MISMATCH, &val_pskey_max_mismatch, sizeof(uint16)) == 0)
            val_pskey_max_mismatch = 0;
        pskey_read = TRUE;
    }

    switch ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant)
	{
	case SBC_DECODER:
		kap_file = "sbc_decoder/sbc_decoder.kap";
      break;
	case MP3_DECODER:
		kap_file = "mp3_decoder/mp3_decoder.kap";
		break;
	case AAC_DECODER:
		kap_file = "aac_decoder/aac_decoder.kap";
		break;
	case FASTSTREAM_SINK:
		kap_file = "faststream_sink/faststream_sink.kap";
		break;
	default:
		Panic();
		break;
	}


   /*ensure that the messages received are from the correct kap file*/
   (void) MessageCancelAll( (TaskData*) task, MESSAGE_FROM_KALIMBA);
   MessageKalimbaTask( (TaskData*) task );


	index = FileFind(FILE_ROOT,(const char *) kap_file ,strlen(kap_file));

	if (index == FILE_NONE)
		Panic();
	if (!KalimbaLoad(index))
		Panic();

    DECODER = (DECODER_t*)PanicUnlessMalloc (sizeof (DECODER_t) ) ;

    DECODER->media_sink = audio_sink ;
    DECODER->codec_task = codec_task ;
    DECODER->volume     = volume;
    DECODER->mode       = mode;
    DECODER->stereo     = stereo;
    DECODER->params     = (uint16) params;
    DECODER->rate       = rate;
    DECODER->app_task	= app_task;

	if ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant == AAC_DECODER)
	{
		/* Workaround for AAC+ sources that negotiate sampling frequency at half the actual value */
		if (rate < 32000)
			DECODER->rate = rate * 2;
	}

   CodecSetOutputGainNow(DECODER->codec_task, 0, left_and_right_ch);

   StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
   StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1));

   PanicFalse(PcmClearRouting(0));
   PanicFalse(PcmClearRouting(1));

   /* For sinks disconnect the source in case its currently being disposed. */
   StreamDisconnect(StreamSourceFromSink(audio_sink), 0);

	PRINT(("DECODER: CsrA2dpDecoderPluginConnect completed\n"));
}