Esempio n. 1
0
/****************************************************************************
NAME	
	linkPolicyPhonebookAccessComplete

DESCRIPTION
	set the link policy requirements back after phonebook access, based on current device audio state 
	
RETURNS
	void
*/
void linkPolicyPhonebookAccessComplete(Sink sink)
{
    typed_bdaddr taddr;
    uint16 DeviceId;
    uint16 StreamId;
    uint8 i;
    bool  a2dpSetting = FALSE;
        
    /* If device is in the stream a2dp state, use a2dp link policy */
    for_all_a2dp(i)
    {
        DeviceId = theSink.a2dp_link_data->device_id[i];
        StreamId = theSink.a2dp_link_data->stream_id[i];
           
        if( SinkGetBdAddr(sink, &taddr) &&
            BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[i], &taddr.addr) )
        {
            a2dpSetting = TRUE;
            if(A2dpMediaGetState(DeviceId, StreamId)== a2dp_stream_streaming)
                linkPolicyUseA2dpSettings(DeviceId, StreamId, A2dpMediaGetSink(DeviceId, StreamId));
            else
                linkPolicyUseHfpSettings(hfp_primary_link, sink);
        }
    }
        
    /* Otherwise, use hfp link policy */
    if(!a2dpSetting)
    {
        linkPolicyUseHfpSettings(hfp_primary_link, sink); 
    }
}
Esempio n. 2
0
void A2dpSendMediaPacketTestExtra(uint16 device_id, uint16 stream_id)
{
    static const uint8 pkt[] = { 0x80, 0x01, 0x50, 0xcf, 0xcb, 0xd7, 0xd0, 0x20, 0xfa, 0x84, 
                                 0xea, 0x9b, 0x05, 0x9c, 0xbd, 0x3b, 0xff, 0xfc, 0xca, 0x88,
                                 0x78, 0x33, 0x98, 0x86, 0x85, 0x66, 0x7f, 0xbe, 0xee, 0xdd };
    Sink media_sink = A2dpMediaGetSink( device_id, stream_id );
    uint8 *dest = SinkMap(media_sink) +  SinkClaim(media_sink, sizeof(pkt));
    memmove(dest, pkt, sizeof(pkt));
    SinkFlush(media_sink, sizeof(pkt));
}
Esempio n. 3
0
/****************************************************************************
NAME 
 CheckVolumeA2dp

DESCRIPTION
 check whether any a2dp connections are present and if these are currently active
 and routing audio to the headset, if that is the case adjust the volume up or down
 as appropriate

RETURNS
 void
    
*/
bool CheckVolumeA2dp(volume_direction dir)
{
    uint8 index;
 
    /* check both possible instances of a2dp connection */
    for(index = a2dp_primary; index < (a2dp_secondary+1); index++)
    {
        /* is a2dp connected? */
        if(theHeadset.a2dp_link_data->connected[index])
        {
            /* check whether the a2dp connection is present and streaming data and that the audio is routed */
            if(theHeadset.sco_sink && (theHeadset.sco_sink == A2dpMediaGetSink(theHeadset.a2dp_link_data->device_id[index], theHeadset.a2dp_link_data->stream_id[index])))
            {
                /* get current volume for this profile */
                uint16 lOldVol = theHeadset.a2dp_link_data->gAvVolumeLevel[index];
                
                /* change up or down */
                if(dir == increase_volume)
                {
                    /* increase volume by one level up to maximum */
                    theHeadset.a2dp_link_data->gAvVolumeLevel[index] = theHeadset.audioData.gVolMaps[lOldVol].IncVol ;
                    /* limit to maximum and send notification event when at max level */
                    if(theHeadset.a2dp_link_data->gAvVolumeLevel[index] >= VOLUME_A2DP_MAX_LEVEL)
                    {
                        theHeadset.a2dp_link_data->gAvVolumeLevel[index] = VOLUME_A2DP_MAX_LEVEL;
                        MessageSend ( &theHeadset.task , EventVolumeMax , 0 );
                    }
                }
                /* decrease volume */
                else
                {
                    /* decrease volume by one level down to minimum */
                    theHeadset.a2dp_link_data->gAvVolumeLevel[index] = theHeadset.audioData.gVolMaps[lOldVol].DecVol ;
                    /* limit to minimum and send notification event when at min level */
                    if(theHeadset.a2dp_link_data->gAvVolumeLevel[index] == VOLUME_A2DP_MIN_LEVEL)
                    {                        
                        MessageSend ( &theHeadset.task , EventVolumeMin , 0 );                                      
                    }
                }                
#ifdef ENABLE_AVRCP    
                {
                    uint16 vol_step_change = 0;
                    if (lOldVol > theHeadset.a2dp_link_data->gAvVolumeLevel[index])
                        vol_step_change = lOldVol - theHeadset.a2dp_link_data->gAvVolumeLevel[index];
                    else
                        vol_step_change = theHeadset.a2dp_link_data->gAvVolumeLevel[index] - lOldVol;
                    headsetAvrcpVolumeStepChange(dir, vol_step_change);                
                }
#endif          
				#if 1
				VolumeSetA2dp(index, lOldVol, dir);
				#else
                VolumeSetA2dp(index, lOldVol);
				#endif
                /* volume adjusted for a A2DP media stream */
                return TRUE;
            }
        }
    }
    /* no routed a2dp media streams found */
    return FALSE;
}
Esempio n. 4
0
/****************************************************************************
NAME    
    sinkCheckPartyModeAudio
    
DESCRIPTION
    Called when checking for PartyMode being enabled, if not enabled no action is
    taken, when enabled decisions are made as to what audio should be playing or
    paused/resumed etc
    
RETURNS
    bool false if party mode not enabled, true is party mode enabled and action has
    been taken with regards to the routing of the audio source
*/
bool sinkCheckPartyModeAudio(audio_sources requested_source, audio_source_status * lAudioStatus)
{
    uint8 index;
    
    /* check whether party mode is enabled and configured and if the currently routed audio is one of the a2dp streams */
    if((theSink.PartyModeEnabled)&&(theSink.features.PartyMode)&&(lAudioStatus->audio_routed)&&
       ((lAudioStatus->a2dpSinkPri == lAudioStatus->audio_routed)||(lAudioStatus->a2dpSinkSec == lAudioStatus->audio_routed))
      )
    {
        /* determine the PartyMode operating mode required */     
        switch(theSink.features.PartyMode)
        {
            /* simple barge-in mode of operation, a new audio source streaming music
               disconnects any currently streaming device */
            case partymode_barge_in:
                PTY_DEBUG(("PTY: bargein\n"));

                /* if the current streaming audio A2DP pri and a stream for A2DP sec is available, switch to that */            
                if((lAudioStatus->a2dpSinkPri == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStateSec == a2dp_stream_streaming))
                {
                    PTY_DEBUG(("PTY: drop current pri route new sec\n"));

                    /* drop bluetooth connection to device currently streaming */
                    for(index = a2dp_primary; index < (a2dp_secondary+1); index++)
                    {
                        /* is a2dp connected? */
                        if(theSink.a2dp_link_data->connected[index])
                        {
                            /* check whether the a2dp connection is present and streaming data and that the audio is routed */
                            if(lAudioStatus->audio_routed == A2dpMediaGetSink(theSink.a2dp_link_data->device_id[index], theSink.a2dp_link_data->stream_id[index]))
                            {                                   
                                /* disconnect a2dp audio device */
                                sinkPartyModeDisconnectDevice(index);
                            }
                        }
                    }
                    /* route the audio from the new device */
                    A2dpRouteAudio(a2dp_secondary, lAudioStatus->a2dpSinkSec);
                }
                /* if the current streaming audio A2DP sec and a stream for A2DP pri is available, switch to that */            
                else if((lAudioStatus->a2dpSinkSec == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStatePri == a2dp_stream_streaming))
                {
                    PTY_DEBUG(("PTY: drop current sec route new pri\n"));
                    /* drop bluetooth connection to device currently streaming */
                    for(index = a2dp_primary; index < (a2dp_secondary+1); index++)
                    {
                        /* is a2dp connected? */
                        if(theSink.a2dp_link_data->connected[index])
                        {
                            /* check whether the a2dp connection is present and streaming data and that the audio is routed */
                            if(lAudioStatus->audio_routed == A2dpMediaGetSink(theSink.a2dp_link_data->device_id[index], theSink.a2dp_link_data->stream_id[index]))
                            {                                   
                                /* disconnect a2dp audio device */
                                sinkPartyModeDisconnectDevice(index);
                            }
                        }
                    }
                    /* route the audio from the new device */
                    A2dpRouteAudio(a2dp_primary, lAudioStatus->a2dpSinkPri);
                }
                /* no action has been taken */
                else
                    return TRUE;
            break;
        
            /* more complex use case, a new streaming audio source is paused using avrcp
               until the current playing track completes */
            case partymode_avrcp_control:
                PTY_DEBUG(("PTY: avrcp ctrl AG1[%x] AG2[%x] AVRCP1[%x] AVRCP[%x] \n",lAudioStatus->a2dpStatePri,lAudioStatus->a2dpStateSec,theSink.avrcp_link_data->play_status[a2dp_primary],theSink.avrcp_link_data->play_status[a2dp_secondary]));

                /* if the current streaming audio is A2DP pri and a stream for A2DP sec is available, pause that and wait for the 
                   current track to finish playing */            
                if((lAudioStatus->a2dpSinkPri == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStatePri == a2dp_stream_streaming)&&
                   ((lAudioStatus->a2dpStateSec == a2dp_stream_streaming)&&
                    (sinkCheckAvrcpStateMatch(a2dp_secondary, avrcp_play_status_playing)))
                   )
                {
                    PTY_DEBUG(("PTY: suspend a2dp sec audio until pri track finished \n"));
                    SuspendA2dpStream(a2dp_secondary);
                    /* set paused flag */
                    theSink.rundata->partymode_pause.audio_source_secondary_paused = TRUE;
                }
                /* if the current streaming audio A2DP sec and a stream for A2DP pri is available, switch to that */            
                else if((lAudioStatus->a2dpSinkSec == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStateSec == a2dp_stream_streaming)&&
                        ((lAudioStatus->a2dpStatePri == a2dp_stream_streaming)&&
                         (sinkCheckAvrcpStateMatch(a2dp_primary, avrcp_play_status_playing)))
                       )
                {
                    PTY_DEBUG(("PTY: suspend a2dp pri audio until sec track finished \n"));
                    SuspendA2dpStream(a2dp_primary);
                    /* set paused flag */
                    theSink.rundata->partymode_pause.audio_source_primary_paused = TRUE;
                }
                /* check if currently routed primary source is still valid, disconnect if not */
                else if((lAudioStatus->a2dpSinkPri == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStatePri != a2dp_stream_streaming))
                {
                    /* check if other source is present and paused */
                    a2dp_link_priority link = sinkPartyModeCheckForOtherPausedSource(a2dp_primary);
                    PTY_DEBUG(("PTY: pri source not valid, disconnect\n"));
                    /* disconnect a2dp primary audio */
                    audioDisconnectActiveSink();
                    /* disconnect primary audio device */
                    if(deviceManagerNumConnectedDevs() > 1)
                        sinkPartyModeDisconnectDevice(a2dp_primary);
                    /* check for other paused audio source to route */                    
                    if((link != a2dp_invalid)&&(theSink.rundata->partymode_pause.audio_source_secondary_paused))
                    {
                        PTY_DEBUG(("PTY: resume paused sec\n"));
                        /* resume paused device */
                        ResumeA2dpStream(a2dp_secondary, lAudioStatus->a2dpStateSec, lAudioStatus->a2dpSinkSec);
                    }
                    return TRUE;                
                }
                /* check if currently routed secondary source is still valid, disconnect if not */
                else if((lAudioStatus->a2dpSinkSec == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStateSec != a2dp_stream_streaming))
                {
                    /* check if other source is present and paused */
                    a2dp_link_priority link = sinkPartyModeCheckForOtherPausedSource(a2dp_secondary);
                    PTY_DEBUG(("PTY: sec source not valid, disconnect\n"));
                    /* disconnect a2dp secondary audio */
                    audioDisconnectActiveSink();
                    /* disconnect secondary audio device */
                    if(deviceManagerNumConnectedDevs() > 1)
                        sinkPartyModeDisconnectDevice(a2dp_secondary);
                    /* check for other paused audio source to route */                    
                    if((link != a2dp_invalid)&&(theSink.rundata->partymode_pause.audio_source_primary_paused))
                    {
                        PTY_DEBUG(("PTY: resume paused pri\n"));
                        /* resume paused device */
                        ResumeA2dpStream(a2dp_primary, lAudioStatus->a2dpStatePri, lAudioStatus->a2dpSinkPri);
                    }
                    return TRUE;                
                }
                /* take no action at this time */
                else
                {
                    PTY_DEBUG(("PTY: avrcp - no action - AR[%x] Pri[%x] Sec[%x]\n",(uint16)lAudioStatus->audio_routed,lAudioStatus->a2dpStatePri,lAudioStatus->a2dpStateSec));
                    return TRUE;
                }
            break;
            
            /* not a valid configuration of operating mode */
            default:
                PTY_DEBUG(("PTY: invalid mode - no action\n"));
                /* default to standard audio routing mode of operation */
                return FALSE;
            break;
                       
        }
        return TRUE;   
    }        
    /* no audio routed or party mode not enabled */
    else
    {
        /* party mode not active or no audio currently routed, take no action and let standard audio routing
           functions take control */
        PTY_DEBUG(("PTY: NOT ACTIVE [%d] or NO AUDIO ROUTED AR[%x] Pri[%x] Sec[%x]\n",(theSink.PartyModeEnabled && theSink.features.PartyMode)
                                                                                     ,(uint16)lAudioStatus->audio_routed
                                                                                     ,(uint16)lAudioStatus->a2dpSinkPri
                                                                                     ,(uint16)lAudioStatus->a2dpSinkSec));
        return FALSE;
    }
}