/****************************************************************************
DESCRIPTION
	Disconnect Sync audio
*/
void CsrSbcEncoderPluginDisconnect( void ) 
{   
    uint16 i;
    
    if (!SBC)
        Panic() ;
            
    StreamDisconnect(0, StreamKalimbaSink(0));

    KalimbaPowerOff() ;
  
    for (i = 0; i < MAX_AUDIO_SINKS; i++)
	{
		if (SBC->media_sink[i] != 0)
		{										
			/* Disconnect the Kalimba source from the media sink */
            StreamDisconnect(StreamKalimbaSource(i+2), SBC->media_sink[i]);
            
            PRINT(("Audio Plugin: Disconnect media i:%d sink:0x%x\n",i,(uint16)SBC->media_sink[i]));
                
            /* clear the audio sink */	
	        SBC->media_sink[i] = 0;			            
		}
	}
        
    free (SBC);
    SBC = NULL ;        
}
/****************************************************************************
DESCRIPTION
    Stop prompt where DSP has not been loaded by the plugin, e.g. (adpcm or pcm) 
    Prompt is either mixing in an existing DSP app or not using the DSP.
*/
static void CsrVoicePresencesPluginStopPhraseMixable ( void ) 
{
    Sink lSink=NULL;
    Task taskdata = NULL;
    
    /* Check for DSP mixing */
    if(GetCurrentDspStatus())
    {
        lSink = StreamKalimbaSink(PRESENT_DSP_PORT);
        /* reset the volume levels of the dsp plugin */
        if(GetAudioPlugin())           	    
            MessageSend( GetAudioPlugin(), AUDIO_PLUGIN_RESET_VOLUME_MSG, 0 ) ;
    }
    else    /* Must be ADPCM not mixing */
    {
        switch(koovox_phrase_data->features.audio_output_type)
        {
            /* is the I2S required? */
            case OUTPUT_INTERFACE_TYPE_I2S:
            {               
                CsrI2SAudioOutputDisconnect( koovox_phrase_data->features.stereo);  
            }
            break;
            
            /* spdif output? */
            case OUTPUT_INTERFACE_TYPE_SPDIF:
            {
                Sink rSink = NULL;
                                
                /* obtain source to SPDIF hardware and disconnect it */
                lSink = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_A );
                rSink = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_B );
                StreamDisconnect(0, lSink);
                StreamDisconnect(0, rSink);
                SinkClose(lSink);
                SinkClose(rSink);
            }
            break;
            
            /* use built in codec */
            default:
            {
                lSink = StreamAudioSink(AUDIO_HARDWARE_CODEC,AUDIO_INSTANCE_0, (koovox_phrase_data->features.stereo ? AUDIO_CHANNEL_A_AND_B : AUDIO_CHANNEL_A));
                /* Disconnect PCM source/sink */
                StreamDisconnect(StreamSourceFromSink(lSink), lSink); 
            }
        }
    }    
    /* close sink and cancel any messages if valid */
    if(lSink)
    {
        /* Cancel all the messages relating to VP that have been sent */
        taskdata = MessageSinkTask(lSink, NULL);
        SinkClose(lSink);
    }
    PRINT(("PRESENT: SinkTask now NULL was %x\n",(uint16)taskdata));
    MessageCancelAll((TaskData*) &csr_voice_presences_plugin, MESSAGE_STREAM_DISCONNECT);
}
Esempio n. 3
0
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
	Stop a tone from currently playing
*/
void CsrA2dpDecoderPluginStopTone ( void )
{
    if (!DECODER)
        Panic() ;

     StreamDisconnect ( 0 , StreamKalimbaSink(3) ) ;
}
/****************************************************************************
DESCRIPTION
	Disconnect Sync audio
*/
void CsrA2dpDecoderPluginDisconnect( void )
{
    if (!DECODER)
        Panic() ;

        /*disconnect the pcm streams*/
    StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
	StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1));

	   /* For sinks disconnect the source in case its currently being disposed. */
    StreamDisconnect(StreamSourceFromSink(DECODER->media_sink ), 0);
    StreamConnectDispose (StreamSourceFromSink(DECODER->media_sink)) ;

    KalimbaPowerOff() ;

    free (DECODER);
    DECODER = NULL ;
}
Esempio n. 6
0
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"));
}
Esempio n. 7
0
/****************************************************************************
NAME 
	hidConnDisconnected
DESCRIPTION
	Called to put the specified connection into the disconnected state.
RETURNS
	void
*/
void hidConnDisconnected(HID *hid, Sink sink)
{
	hidConnection *conn = NULL;

	/* Find connection structure */
	if (((hid->connection[HID_CON_CONTROL].state == hidConConnected) || (hid->connection[HID_CON_CONTROL].state == hidConDisconnecting)) &&
		(sink == hid->connection[HID_CON_CONTROL].con.sink))
			conn = &hid->connection[HID_CON_CONTROL];
	else if (((hid->connection[HID_CON_INTERRUPT].state == hidConConnected) || (hid->connection[HID_CON_INTERRUPT].state == hidConDisconnecting)) &&
		(sink == hid->connection[HID_CON_INTERRUPT].con.sink))
			conn = &hid->connection[HID_CON_INTERRUPT];
	else
		Panic();
		
	/* Dispose of any messages left in the l2cap sources to ensure the buffers are destroyed */
	StreamDisconnect(StreamSourceFromSink(sink), 0);
	StreamConnectDispose(StreamSourceFromSink(sink));		

	/* Move connection into disconnected state */
	conn->state = hidConDisconnected;
}
/****************************************************************************
DESCRIPTION
    disconnect the subwoofer if currently connected
*/
void CsrA2dpDecoderPluginDisconnectSubwoofer(void)
{
    DECODER_t * DECODER = CsrA2dpDecoderGetDecoderData();
    
    /* ensure the decoder is loaded */
    if(DECODER)
    {
        A2dpPluginConnectParams *codecData = (A2dpPluginConnectParams *) DECODER->params;

        /* if the sub woofer is connected then disconnect it */
        if(codecData->sub_connection_port != DSP_SUB_PORT_NOT_CONNECTED)
        {
            PRINT(("DECODER: CsrA2dpDecoderPluginDisconnect disconnect sub\n"));
    
            /* disconnect kalimba port, this causes dsp app to switch clock source internally */
            StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), codecData->sub_sink );
    
            /* update connected ports state */
            codecData->sub_connection_port = DSP_SUB_PORT_NOT_CONNECTED;
        }
    }
}
/****************************************************************************
DESCRIPTION
    Stop a prompt from currently playing
*/
void CsrVoicePresencesPluginStopPhrase ( void ) 
{
    if(!koovox_phrase_data)
        Panic();
            
    PRINT(("PRESENT: Terminated\n"));
                
    if(koovox_phrase_data->mixing)
    {
        /* If DSP already loaded and the prompt was mixed */         
        CsrVoicePresencesPluginStopPhraseMixable();
    }
	
    /* Make sure prompt source is disposed */
    if(SourceIsValid(koovox_phrase_data->source))
        StreamDisconnect(koovox_phrase_data->source, NULL);
    
    /* Tidy up */
    free(koovox_phrase_data);
    koovox_phrase_data = NULL;
    SetAudioBusy(NULL) ;
    SetVpPlaying(FALSE);
    
}
Esempio n. 10
0
void A2dpStartKalimbaStreaming(const A2DP *a2dp, uint16 media_sink)
{
    FILE_INDEX index = FILE_NONE;

#ifdef BUILD_FOR_23FW
    Transform t;    
#else    
    Transform t, l_t, r_t;
    
    Source l_src = StreamAudioSource(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A);
    Source r_src = StreamAudioSource(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_1, AUDIO_CHANNEL_B);
    Sink   l_snk = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A);
    Sink   r_snk = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_1, AUDIO_CHANNEL_B);
#endif
    
    /* load SBC codec */
    index = FileFind(FILE_ROOT, sbc_encoder, sizeof(sbc_encoder)-1);
    if (!KalimbaLoad(index))
        /* codec load failure, Panic as the test isn't going to work now */
        Panic();

    /* Init and configure RTP */
    t = TransformRtpSbcEncode(StreamKalimbaSource(0), (Sink)media_sink);
    TransformConfigure(t, VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, 668);
    TransformConfigure(t, VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE);
    (void)TransformStart(t);

    /* Configure SBC encoding format */
    (void)PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_PARAMS, 0x00bd, 0, 0, 0));
    (void)PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_BITPOOL, 0x0030, 0, 0, 0));

#ifdef BUILD_FOR_23FW
    StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
    StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1));

    /* set up ADCs */
    (void)PcmClearAllRouting();
    (void)PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, 44100, 44100, VM_PCM_INTERNAL_A));
    (void)PanicFalse(PcmRateAndRoute(1, 0, 44100, 44100, VM_PCM_INTERNAL_B));
    (void)PanicFalse(StreamConnect(StreamPcmSource(0),StreamKalimbaSink(0)));
    (void)PanicFalse(StreamConnect(StreamPcmSource(1),StreamKalimbaSink(1)));

#else
    SourceClose(l_src);
    SourceClose(r_src);
    SinkClose(l_snk);
    SinkClose(r_snk);
    
    (void) SourceConfigure(l_src, STREAM_CODEC_INPUT_RATE, 44100);
    (void) SourceConfigure(r_src, STREAM_CODEC_INPUT_RATE, 44100);
    (void) SourceSynchronise(l_src, r_src);
    
    /* set up ADCs */
    l_t = StreamConnect(l_src, StreamKalimbaSink(0));
    r_t = StreamConnect(r_src, StreamKalimbaSink(1));
    (void)TransformStart(l_t);
    (void)TransformStart(r_t);
#endif
    
    /* Start decode */
    (void) PanicFalse(KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0));
}
/****************************************************************************
DESCRIPTION
    configure the sub woofer and connect its audio if present
*/
void CsrA2dpDecoderPluginSetSubWoofer(AUDIO_SUB_TYPE_T sub_type, Sink sub_sink)
{
    DECODER_t * DECODER = CsrA2dpDecoderGetDecoderData();
    
    /* ensure the decoder is loaded */
    if(DECODER)
    {
        A2dpPluginConnectParams *codecData = (A2dpPluginConnectParams *) DECODER->params;

        /* update the decoder params with the new sub woofer status */
        codecData->sub_woofer_type = sub_type;
        codecData->sub_sink = sub_sink;

        /* determine sub woofer type and connect (or disconnect if gone away) the sink
           to the appropriate dsp port */
        switch(sub_type)
        {
            /* SUB no longer available, disconnect port if still connected */
            case AUDIO_SUB_WOOFER_NONE:
                PRINT(("DECODER: Disconnect woofer\n" ));
                /* if source is still connected then disconnect it */
                if(codecData->sub_connection_port != DSP_SUB_PORT_NOT_CONNECTED)
                {
                    /* determine if the subwoofer has connected after the decoder was loaded,
                       configured and unmuted */
                    if(codecData->sub_is_available == FALSE)
                    {
                        /* mute the outputs whilst the subwoofer port is connected and
                           decoder restarted */
                        csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_ENABLE);
                    }

                    PRINT(("DECODER: Disconnect kalimba port %x\n", codecData->sub_connection_port));
                    StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), 0);                 
                    /* update connected ports state */
                    codecData->sub_connection_port = DSP_SUB_PORT_NOT_CONNECTED;
                    /* set volume levels to desired level */
                    SubConnectedNowUnmuteVolume(DECODER);
                    
                    /* determine if the subwoofer has connected after the decoder was loaded,
                       configured and unmuted */
                    if(codecData->sub_is_available == FALSE)
                    {
                        /* unmute the outputs again */
                        csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_DISABLE);
                    }
                }
            break;

            /* SUB using esco as its bt link, connect to dsp port 2 */
            case AUDIO_SUB_WOOFER_ESCO:
                PRINT(("DECODER: connect esco dsp port 2, sub_sink = %x\n", (uint16)sub_sink ));
                /* ensure the correct ype of link is requested */
                if(DECODER->sink_type != AUDIO_SINK_AV)
                {               
                    /* connect SUB output from dsp, source port 2, to esco sink  */
                    if(codecData->sub_connection_port != DSP_ESCO_SUB_PORT)
                    {
                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* mute the outputs whilst the subwoofer port is connected and
                               decoder restarted */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_ENABLE);
                        }
                        
                        /* if not already connected */
                        if(codecData->sub_connection_port == DSP_L2CAP_SUB_PORT)
                        {
                            /* wrong port connected, disconnect it first */
                            StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), 0);
                            PRINT(("DECODER: Disconnect kalimba port %x\n", codecData->sub_connection_port));
                        }
                        /* ensure sink is valid */
                        if(SinkIsValid(sub_sink))
                        {
                            /* connect esco (2) port */
                            if(StreamConnect(StreamKalimbaSource(DSP_ESCO_SUB_PORT),sub_sink))
                            {
                                /* update connected ports state */
                                codecData->sub_connection_port = DSP_ESCO_SUB_PORT;
                                PRINT(("DECODER: Connect kalimba port %x\n", codecData->sub_connection_port));
                                /* set volume levels to desired level */
                                SubConnectedNowUnmuteVolume(DECODER);
                            }
                            else
                                PRINT(("DECODER: connect esco dsp port 2 FAILED\n" ));
                        }
                        else
                        {
                            PRINT(("DECODER: connect esco dsp port 2, sub_sink = %x NOT VALID\n", (uint16)sub_sink ));
                        }

                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* unmute the outputs again */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_DISABLE);
                        }

                    }
                }
                else
                    PRINT(("DECODER: ESCO - ****wrong link type****\n"));                    
            break;

            /* SUB using l2cap as its bt link, connect to dsp port 3 */
            case AUDIO_SUB_WOOFER_L2CAP:
                PRINT(("DECODER: connect l2cap dsp port 3, sub_sink = %x\n", (uint16)sub_sink ));
                /* ensure the correct ype of link is requested */
                if(DECODER->sink_type == AUDIO_SINK_AV)
                {
                    /* connect SUB output from dsp, source port 2, to esco sink  */
                    if(codecData->sub_connection_port != DSP_L2CAP_SUB_PORT)
                    {
                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* mute the outputs whilst the subwoofer port is connected and
                               decoder restarted */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_ENABLE);
                        }

                        /* if not already connected */
                        if(codecData->sub_connection_port == DSP_ESCO_SUB_PORT)
                        {
                            /* wrong port connected, disconnect it first */
                            StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), 0);
                            PRINT(("DECODER: Disconnect kalimba port %x\n", codecData->sub_connection_port));
                        }
    
                        /* ensure sink is valid */
                        if(SinkIsValid(sub_sink))
                        {
                            /* connect l2cap (3) port */
                            if(StreamConnect(StreamKalimbaSource(DSP_L2CAP_SUB_PORT),sub_sink))
                            {
                                /* update connected ports state */
                                codecData->sub_connection_port = DSP_L2CAP_SUB_PORT;
                                PRINT(("DECODER: Connect kalimba port %x\n", codecData->sub_connection_port));
                                /* set volume levels to desired level */
                                SubConnectedNowUnmuteVolume(DECODER);
                            }
                            else
                                PRINT(("DECODER: connect l2cap dsp port 3 FAILED\n" ));
                        }
                        else
                        {
                            PRINT(("DECODER: connect l2cap dsp port 3, sub_sink = %x NOT VALID\n", (uint16)sub_sink ));
                        }
                        
                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* unmute the outputs again */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_DISABLE);
                        }
                    }
                }
                else
                    PRINT(("DECODER: L2CAP - ****wrong link type****\n"));                                        
            break;
        }
    }
    else
        PRINT(("DECODER: CsrA2dpDecoderPluginSetSubWoofer ERROR NO DECODER\n" ));
}
/****************************************************************************
DESCRIPTION
	This function connects a synchronous audio stream to the pcm subsystem
*/ 
void CsrSbcEncoderPluginConnect( Sink audio_sink , Task codec_task , uint16 volume , uint32 rate , bool stereo , AUDIO_MODE_T mode , const void * params ) 
{
	/* DSP Application loading and Transform starting is handled by a call to A2dpAudioCodecEnable
		in the application, so should not be done here. */

	typedef struct
	{
		unsigned source_type:4;
		unsigned reserved:4;
		uint8 content_protection;
		uint32 voice_rate;
		unsigned bitpool:8;
		unsigned format:8;
		uint16 packet_size;
		Sink media_sink_b;
	} sbc_codec_data_type;

	sbc_codec_data_type *sbc_codecData = (sbc_codec_data_type *) params;

	if (!sbc_codecData)
		Panic();

    SBC = (SBC_t*)PanicUnlessMalloc (sizeof (SBC_t) ) ;
    
    SBC->media_sink[0] = audio_sink ;
    SBC->codec_task = codec_task ;
	SBC->media_sink[1] = sbc_codecData->media_sink_b;
	SBC->packet_size = sbc_codecData->packet_size;
    
    StreamDisconnect(StreamKalimbaSource(2), 0);

	/* Initialise the RTP SBC encoder */
	SBC->t[0] = TransformRtpSbcEncode(StreamKalimbaSource(2), audio_sink);

	/* Configure the RTP transform to generate the selected packet size */
	TransformConfigure(SBC->t[0], VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, sbc_codecData->packet_size);

	/* Transform should not manage timings. */
	TransformConfigure(SBC->t[0], VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE);

	/* Start the transform */
	(void) TransformStart(SBC->t[0]);
    
    PRINT(("Audio Plugin: TransformStart sink:0x%x\n",(uint16)audio_sink));
	
	if (SBC->media_sink[1])
	{
		/* There is a 2nd audio stream so initialise this transform */
        StreamDisconnect(StreamKalimbaSource(3), 0);
		
		/* Initialise the RTP SBC encoder */
		SBC->t[1] = TransformRtpSbcEncode(StreamKalimbaSource(3), SBC->media_sink[1]);

		/* Configure the RTP transform to generate the selected packet size */
		TransformConfigure(SBC->t[1], VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, sbc_codecData->packet_size);

		/* Transform should not manage timings. */
		TransformConfigure(SBC->t[1], VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE);

		/* Start the transform */
		(void) TransformStart(SBC->t[1]);
        
        PRINT(("Audio Plugin: TransformStart sink:0x%x\n",(uint16)SBC->media_sink[1]));
	}

	/* Configure SBC encoding format */
	if (!KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_PARAMS, sbc_codecData->format, 0, 0, 0))
		/* If message fails to get through, abort */
		Panic();

	/* Pass bit pool value to DSP */
	if (!KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_BITPOOL, sbc_codecData->bitpool, 0, 0, 0))
		/* If message fails to get through, abort */
		Panic();

	/* disard any data sent by the SNK */
    StreamConnectDispose(StreamSourceFromSink(audio_sink));
	
	if (SBC->media_sink[1])
	{
		/* disard any data sent by the 2nd SNK */
	    StreamConnectDispose(StreamSourceFromSink(SBC->media_sink[1]));
	}
	
	/* select the source type */
	if(sbc_codecData->source_type == SourceUsb)
	{
		PRINT(("Audio Plugin: SourceUsb\n"));
		/* Select the source type */
		PanicFalse(KalimbaSendMessage(KALIMBA_ENCODER_SELECT, 0x0001, 0, 0, 0));
	}
	else
	{
		PRINT(("Audio Plugin: SourceAnalog\n"));
		/* For analogue input source */
		StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
		StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1));
        
		(void)PcmClearAllRouting();

		if (CodecGetCodecType(codec_task) == codec_wm8731)
		{
			PRINT(("Audio Plugin: codec_wm8731\n"));
			/* configure slot 0 and 1 to be left and right channel
			and synchronise the offsets for stereo playback */
			(void)PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) rate, (uint32) rate, VM_PCM_EXTERNAL_I2S);
			(void)PcmRateAndRoute(1, 0, (uint32) rate, (uint32) rate, VM_PCM_EXTERNAL_I2S);
		}
		else
		{
			PRINT(("Audio Plugin: codec_internal\n"));
			/* configure slot 0 and 1 to be left and right channel
			and synchronise the offsets for stereo playback */
			(void)PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) rate, (uint32) rate, VM_PCM_INTERNAL_A);
			(void)PcmRateAndRoute(1, 0, (uint32) rate, (uint32) rate, VM_PCM_INTERNAL_B);
		}
		        
		/* plug Left ADC into port 0 */
		(void)StreamConnect(StreamPcmSource(0),StreamKalimbaSink(0)); 

		/* plug Right ADC into port 1 */
		(void)StreamConnect(StreamPcmSource(1),StreamKalimbaSink(1)); 
		
		/* Select the source type */
		PanicFalse(KalimbaSendMessage(KALIMBA_ENCODER_SELECT, 0x0002, 0, 0, 0)); 
		
		if(!KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0))
		{
			PRINT(("SBC: Message KALIMBA_MSG_GO failed!\n"));
			Panic();
		}
	}

	/* Select the source type */
	/*PanicFalse(KalimbaSendMessage(KALIMBA_SOURCE_SELECT, SOURCE_USB, 0, 0, 0)); */
	
    /*CsrSbcEncoderUsbPluginSetVolume(volume) ;*/
	
	/*(void) StreamConnect(PanicNull(StreamUsbEndPointSource(end_point_iso_in)), StreamKalimbaSink(0));
    */
	/* Start decode */
   /* if(!KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0))
	{
		PRINT(("SBC: Message KALIMBA_MSG_GO failed!\n"));
		Panic();
	}
	*/
}
/****************************************************************************
DESCRIPTION
	Set the mode
*/
void CsrSbcEncoderPluginSetMode ( AUDIO_MODE_T mode , const void * params ) 
{   
	typedef struct
	{
		bool connect_sink;
		Sink media_sink;
	} sbc_mode_params;
	
	sbc_mode_params *sbc_mode = (sbc_mode_params *) params;
	uint16 i;
	
    if (!SBC)
       	Panic() ;
           
    PRINT(("Audio Plugin: Set Mode\n"));
	
	if (sbc_mode->connect_sink)
	{
		/* A second audio sink has been connected */
		for (i = 0; i < MAX_AUDIO_SINKS; i++)
		{
			if (SBC->media_sink[i] == 0)
			{
				/* store the audio sink */	
				SBC->media_sink[i] = sbc_mode->media_sink;	
						
				/* Initialise the RTP SBC encoder */
				SBC->t[i] = TransformRtpSbcEncode(StreamKalimbaSource(i+2), SBC->media_sink[i]);

				/* Configure the RTP transform to generate the selected packet size */
				TransformConfigure(SBC->t[i], VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, SBC->packet_size);

				/* Transform should not manage timings. */
				TransformConfigure(SBC->t[i], VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE);

				/* Start the transform */
				(void) TransformStart(SBC->t[i]);	
                
                PRINT(("Audio Plugin: Start new Transform i:%d sink:0x%x\n",i,(uint16)SBC->media_sink[i]));
			}
		}
	}
	else
	{
		/* An audio sink has been disconnected */
		for (i = 0; i < MAX_AUDIO_SINKS; i++)
		{
			if (SBC->media_sink[i] == sbc_mode->media_sink)
			{										
				/* Disconnect the Kalimba source from the media sink */
                StreamDisconnect(StreamKalimbaSource(i+2), SBC->media_sink[i]);
                
                PRINT(("Audio Plugin: Disconnect media i:%d sink:0x%x\n",i,(uint16)SBC->media_sink[i]));
                
                /* clear the audio sink */	
				SBC->media_sink[i] = 0;			                
			}
		}
	}
    free(sbc_mode);
}
/****************************************************************************
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"));
}
/****************************************************************************
DESCRIPTION
	Connect the encoded audio input and pcm audio output streams
*/
static void MusicConnectAudio (A2dpPluginTaskdata *task, bool stereo )
{
   plugin_codec_data_type *codecData = (plugin_codec_data_type *) DECODER->params;
   uint32 voice_rate = 0;
   
   val_clock_mismatch = codecData->clock_mismatch;
   
   if ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant == FASTSTREAM_SINK)
	{
      /*
         FastStream does not use RTP.
         L2CAP frames enter/leave via port 2
      */
      
    	/*
         Initialise PCM.
         Output stereo at 44k1Hz or 48kHz, input from left ADC at 16kHz.
      */
      
      /* If no voice rate is set just make the ADC rate equal to 16kHz */
      if (!codecData->voice_rate)
         voice_rate = 16000;
      else
         voice_rate = codecData->voice_rate;
      
      PRINT(("FASTSTREAM: rate=0x%lx voice_rate=0x%lx\n format=0x%x bitpool=0x%x",DECODER->rate,codecData->voice_rate,codecData->format,codecData->bitpool));
      PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, (uint32)DECODER->rate, (uint32) voice_rate, VM_PCM_INTERNAL_A));     
      
      /* is it mono playback? */
      if ( !stereo )
      {
         PRINT(("DECODER: Mono\n"));
         /* Connect Kalimba to PCM */
         if (DECODER->rate)
         {
            StreamDisconnect(StreamSourceFromSink(DECODER->media_sink), 0);
            PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0)));
            PanicFalse(StreamConnect(StreamSourceFromSink(DECODER->media_sink),StreamKalimbaSink(2)));
         }
      }
      else
      {
         PRINT(("DECODER: Stereo\n"));
         PanicFalse(PcmRateAndRoute(1, 0, (uint32)DECODER->rate, (uint32) voice_rate, VM_PCM_INTERNAL_B));
         /* Connect Kalimba to PCM */
         if (DECODER->rate)
         {
            StreamDisconnect(StreamSourceFromSink(DECODER->media_sink), 0);
            PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0)));
            PanicFalse(StreamConnect(StreamKalimbaSource(1),StreamPcmSink(1)));
            PanicFalse(StreamConnect(StreamSourceFromSink(DECODER->media_sink),StreamKalimbaSink(2)));
         }
      }

      if (codecData->voice_rate)
      {
         StreamDisconnect(0, DECODER->media_sink);
         /* configure parameters */
         PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_PARAMS, codecData->format, 0, 0, 0));
         PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_BITPOOL, codecData->bitpool, 0, 0, 0));
         PanicFalse(StreamConnect(StreamPcmSource(0), StreamKalimbaSink(0)));
         PanicFalse(StreamConnect(StreamKalimbaSource(2),DECODER->media_sink));
      }
     
   }
   
   else /* Not FastStream CODEC */
	{
		uint8 content_protection = codecData->content_protection;
		uint16 scms_enabled = 0;
		Transform rtp_transform = 0;

		switch ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant)
		{
		case SBC_DECODER:
			rtp_transform = TransformRtpSbcDecode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(0));
			break;
		case MP3_DECODER:
			rtp_transform = TransformRtpMp3Decode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(0));
			break;
		case AAC_DECODER:
			rtp_transform = TransformRtpAacDecode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(0));
			break;
		default:
			break;
		}

		/* Configure the content protection */
		if (content_protection)
			scms_enabled = 1;

		TransformConfigure(rtp_transform, VM_TRANSFORM_RTP_SCMS_ENABLE, scms_enabled);

		/*start the transform decode*/
    	(void)TransformStart( rtp_transform ) ;   

    	/* is it mono playback? */
		if ( !stereo )
		{
			PcmRateAndRoute(0, PCM_NO_SYNC, DECODER->rate, (uint32) 8000, VM_PCM_INTERNAL_A) ;
			PRINT(("DECODER: Mono\n"));
			/* plug port 0 into both DACs */
    		(void) PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0)));
		}
		else
		{
	    	PRINT(("DECODER: Stereo\n"));

	    	PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, DECODER->rate, (uint32) 8000, VM_PCM_INTERNAL_A));
			PanicFalse(PcmRateAndRoute(1, 0, DECODER->rate, (uint32) 8000, VM_PCM_INTERNAL_B));

		    /* plug port 0 into Left DAC */
    		PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0)));
        	/* plug port 1 into Right DAC */
			PanicFalse(StreamConnect(StreamKalimbaSource(1),StreamPcmSink(1)));
		}
   }
         
    	CsrA2dpDecoderPluginSetVolume(task,DECODER->volume) ;

		/* The DSP must know the sample rate for tone mixing */
		KalimbaSendMessage(MESSAGE_SET_SAMPLE_RATE, DECODER->rate, val_pskey_max_mismatch, val_clock_mismatch, 0);
      PRINT(("DECODER: Send Go message to DSP now\n"));
		if(!KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0))
		{
			PRINT(("DECODER: Message KALIMBA_MSG_GO failed!\n"));
			Panic();
		}
      
   }
/****************************************************************************
DESCRIPTION
    This function connects APTX low delay audio 
****************************************************************************/
void MusicConnectAptxLowLatency(A2dpPluginConnectParams *codecData, uint8 content_protection)
{
    Sink speaker_snk_a = NULL;
    Transform rtp_transform = 0;
    DECODER_t * DECODER = CsrA2dpDecoderGetDecoderData();
    
    /* when configured for using back channel low latency apps */
    if(isCodecLowLatencyBackChannel())
    {
        /* if the back channel is required and the mic/line input is configured */
        if (codecData->voice_rate)
        {
            /* Bidirectional channel uses faststream mono with the following settings */
            /*
               Configure the SBC format for the microphone data
               16kHz, Mono, Blocks 16, Sub-bands 8, Loudness, Bitpool = 32
               (data rate = 72kbps, packet size = 3*72 + 4 = 220 <= DM5).
            */
           codecData->format     = 0x31;
           codecData->bitpool    = 32;
           PRINT(("DECODER: apt-X Low Latency Bidirectional rate=0x%lx voice_rate=0x%lx\n format=0x%x\n",DECODER->rate,codecData->voice_rate,codecData->format));
        }
    }

    /* ensure the sample rate is valid */
    if (DECODER->rate)
    {
        /* disconnect media sink as it might be disposed */
        StreamDisconnect(StreamSourceFromSink(DECODER->media_sink), 0);

                /* determine the output hardware type */
        switch(DECODER->features.audio_output_type)
        {
            /* using the inbuilt dacs */
            case OUTPUT_INTERFACE_TYPE_NONE:
            case OUTPUT_INTERFACE_TYPE_DAC:
            {
                /* configure built-in audio hardware channel A */
                speaker_snk_a = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A);
                PanicFalse(SinkConfigure(speaker_snk_a, STREAM_CODEC_OUTPUT_RATE, DECODER->rate));
    
                /* if STEREO mode configured then connect the output channel B */
                if(DECODER->features.stereo)
                {
                    Sink speaker_snk_b = NULL;
        
                    PRINT(("DECODER: Stereo\n"));
        
                    /* connect channels B */
                    speaker_snk_b = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_B);
                    /* configure channel to required rate */
                    PanicFalse(SinkConfigure(speaker_snk_b, STREAM_CODEC_OUTPUT_RATE, DECODER->rate));
                    /* synchronise both sinks for channels A & B */
                    PanicFalse(SinkSynchronise(speaker_snk_a, speaker_snk_b));
                    /* plug port 1 into Right DAC */
                    PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT),speaker_snk_a));
                    PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT),speaker_snk_b));
                }
                /* mono operation, only connect left port */
                else
                {
                    /* plug port 0 into Left DAC */
                    PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT),speaker_snk_a));
                }
            }
            break;

            /* using the spdif digital output hardware */
            case OUTPUT_INTERFACE_TYPE_SPDIF:
            {
                Sink speaker_snk_b = NULL;
                /* configure spdif audio hardware channel 0 */
                speaker_snk_a = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_A);
                speaker_snk_b = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_B);
                /* configure channel to required rate */
                PanicFalse(SinkConfigure(speaker_snk_a,  STREAM_SPDIF_OUTPUT_RATE, DECODER->rate));
                PanicFalse(SinkConfigure(speaker_snk_b,  STREAM_SPDIF_OUTPUT_RATE, DECODER->rate));
                /* connect channels B */
                /* synchronise both sinks for channels A & B */
                PanicFalse(SinkSynchronise(speaker_snk_a, speaker_snk_b));
                /* plug port 1 into Right DAC */
                PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT),speaker_snk_a));
                PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT),speaker_snk_b));   
      
                PRINT(("DECODER: Stereo\n"));
            }
            break;
            
            /* using the i2s digital output hardware */
            case OUTPUT_INTERFACE_TYPE_I2S:
            {
                /* is a specified output frequency required? use resampling*/
                if(CsrI2SMusicResamplingFrequency())
                    CsrI2SAudioOutputConnect(CsrI2SMusicResamplingFrequency(), DECODER->features.stereo, StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT), StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT));                                 
                /* use the negotiated sample rate of the input, no resampling required */                
                else
                    CsrI2SAudioOutputConnect(DECODER->rate, DECODER->features.stereo, StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT), StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT));                                                                
            }            
            break;
        }
    
        /* if content protection is required feed the media sink through the rtp decoder transform */
        if (content_protection)
        {
            rtp_transform = TransformRtpDecode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(LOW_LATENCY_CODEC_TO_DSP_PORT));
            TransformConfigure(rtp_transform, VM_TRANSFORM_RTP_SCMS_ENABLE, content_protection);
            /*start the transform decode*/
            PRINT(("aptX: RTP Transform \n"));
            (void)TransformStart( rtp_transform ) ;
        }
        /* connect the media sink to the dsp input port */
        else
        {
            PanicFalse(StreamConnect(StreamSourceFromSink(DECODER->media_sink),StreamKalimbaSink(LOW_LATENCY_CODEC_TO_DSP_PORT)));
        }
    }
    
    /* Send parameters that configure the SRA and buffer settings */
    PRINT(("aptX LL params: initial level=%d target level=%d sra max rate=%d/10000 sra avg time=%d good working buffer level=%d \n",
           codecData->aptx_sprint_params.target_codec_level,codecData->aptx_sprint_params.initial_codec_level,
           codecData->aptx_sprint_params.sra_max_rate,codecData->aptx_sprint_params.sra_avg_time,
           codecData->aptx_sprint_params.good_working_level));
    KalimbaSendMessage(MESSAGE_SET_APTX_LL_PARAMS1, codecData->aptx_sprint_params.target_codec_level,
                       codecData->aptx_sprint_params.initial_codec_level,
                       codecData->aptx_sprint_params.sra_max_rate,   /* Third field is scaled by 10000 */
                       codecData->aptx_sprint_params.sra_avg_time);
    KalimbaSendMessage(MESSAGE_SET_APTX_LL_PARAMS2, codecData->aptx_sprint_params.good_working_level,
                       0, 0, 0);

    /* update the current audio state */
    SetAudioInUse(TRUE);
}