Sound output issues when switching from A2DP to handsfree

赵成义 zhaochengyi at uniontech.com
Mon Aug 5 10:54:05 UTC 2024


Hi guys,


When switching from A2DP to handsfree, it will automatically switch to other ports 
and output audio for a short time, and then immediately switch to the handsfree output port.


How can we fix this issue? Thanks a lot.



In the following set_profile_cb function, this issue occurs after the stop_thread function calls 
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s) in pa_sink_unlink.
------------------------
static int set_profile_cb(pa_card *c, pa_card_profile *new_profile) {
    struct userdata *u;
    pa_bluetooth_profile_t *p;


    pa_assert(c);
    pa_assert(new_profile);
    pa_assert_se(u = c->userdata);


    p = PA_CARD_PROFILE_DATA(new_profile);


    if (*p != PA_BLUETOOTH_PROFILE_OFF) {
        const pa_bluetooth_device *d = u->device;


        if (!d->transports[*p] || d->transports[*p]->state <= PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED) {
            pa_log_warn("Refused to switch profile to %s: Not connected", new_profile->name);
            return -PA_ERR_IO;
        }
    }


    stop_thread(u);


    u->profile = *p;


    if (u->profile != PA_BLUETOOTH_PROFILE_OFF)
        if (init_profile(u) < 0)
            goto off;


    if (u->sink || u->source)
        if (start_thread(u) < 0)
            goto off;


    return 0;


off:
    stop_thread(u);


    pa_assert_se(pa_card_set_profile(u->card, pa_hashmap_get(u->card->profiles, "off"), false) >= 0);


    return -PA_ERR_IO;
}



static void stop_thread(struct userdata *u) {
    pa_assert(u);


    if (u->sink || u->source)
        pa_proplist_unset(u->card->proplist, PA_PROP_BLUETOOTH_CODEC);


    if (u->sink)
        pa_sink_unlink(u->sink);


    /* Omitted */


}


void pa_sink_unlink(pa_sink* s) {
    bool linked;
    pa_sink_input *i, PA_UNUSED *j = NULL;


    pa_sink_assert_ref(s);
    pa_assert_ctl_context();


    /* Please note that pa_sink_unlink() does more than simply
     * reversing pa_sink_put(). It also undoes the registrations
     * already done in pa_sink_new()! */


    if (s->unlink_requested)
        return;


    s->unlink_requested = true;


    linked = PA_SINK_IS_LINKED(s->state);


    if (linked)
        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);


    /* Omitted */
}

------------------


Thanks,
Chengyi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-discuss/attachments/20240805/e5401ac2/attachment.htm>


More information about the pulseaudio-discuss mailing list