16.04 Impossible d'utiliser des écouteurs Bluetooth A2DP, les paires mais ne se connecte pas. Journaux à l'intérieur


15

Tout d'abord, j'ai essayé de suivre les deux: https://vilimpoc.org/blog/2016/04/30/ubuntu-16-04-bluetooth-speakers/ et PulseAudio ne peut pas charger le module bluetooth 15.10 / 16.04 / 16.10

Lorsque j'essaie de connecter mon Jaybird X2 (essayé sur ordinateur de bureau et portable, Broadcom et Intel), il se couple, se connecte pendant deux secondes puis se déconnecte.

Journal forme syslog (depuis mon bureau avec broadcom BT)

May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] socket-server.c: bind(): Address already in use
May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] module.c: Failed to load module "module-cli-protocol-unix" (argument: ""): initialization failed.
May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] socket-server.c: bind(): Address already in use
May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] module.c: Failed to load module "module-cli-protocol-unix" (argument: ""): initialization failed.

Et d'autres fois:

a2dp-sink profile connect failed for xxxxxxx Protocol not available

MODIFIER .. IMPORTANT:

J'ai découvert que la plupart du temps, essayer de se connecter à d'autres appareils fonctionne bien (Micropod BT et Samsung AirTrack), mais dès que j'essaye Jaybird X2, il désactive / décharge le module-bluetooth-discovery et je dois le faire pactl load-module module-bluetooth-discoverpour le deux autres pour fonctionner à nouveau ..

Maintenant, cela se produit avec un ordinateur portable:

May 31 17:02:58 vooze-x1 pulseaudio[3534]: [pulseaudio] backend-native.c: connect(): Function not implemented
May 31 17:02:58 vooze-x1 pulseaudio[3534]: [pulseaudio] volume.c: Assertion 'pa_channels_valid(channels)' failed at pulse/volume.c:74, function pa_cvolume_set(). Aborting.
May 31 17:02:58 vooze-x1 bluetoothd[865]: Endpoint unregistered: sender=:1.130 path=/MediaEndpoint/A2DPSource
May 31 17:02:58 vooze-x1 bluetoothd[865]: Endpoint unregistered: sender=:1.130 path=/MediaEndpoint/A2DPSink
May 31 17:03:00 vooze-x1 pulseaudio[3764]: [pulseaudio] main.c: User-configured server at {ddcf951d58914c47b9adca0056c50142}unix:/run/user/1000/pulse/native, which appears to be local. Probing deeper.
May 31 17:03:00 vooze-x1 pulseaudio[3767]: [pulseaudio] pid.c: Stale PID file, overwriting.

J'ai pu brièvement le connecter sur mon bureau auparavant, mais A2DP ne fonctionnait pas la plupart du temps ..

Deux erreurs différentes mais même problème. Que se passe-t-il?

Le bluetooth vient-il juste d'être cassé dans Ubuntu 16.04? Cela fonctionne sous Windows et avec mon téléphone Android.

Toute aide serait géniale! :) J'ai en quelque sorte réussi à le faire fonctionner brièvement, d'abord cela a fonctionné, puis A2DP n'a pas fonctionné .. donc je soupçonne que cela a quelque chose à voir avec A2DP. Pas certain.


Avez-vous mis votre casque en mode d'appairage avant de vous connecter? Depuis l'appareil éteint, maintenez la touche centrale enfoncée pendant 4 s jusqu'à ce que le voyant rouge / vert clignote. Recherchez-le dans Ubuntu et connectez-vous. Voir askubuntu.com/questions/259354/…
Takkat

Oui, et il se marie très bien .. Le problème n'est pas le couplage, mais la "connexion" .. Il se connecte et dit "casque connecté" puis se déconnecte 2 secondes après.
Joakim Koed

Je demande simplement parce que c'est un symptôme de périphériques mal appariés qui semblent se connecter mais échouer. Il peut être utile de réessayer (après avoir retiré le périphérique des périphériques connus).
Takkat

Takket: Je l'ai probablement fait 20 fois. casque à réinitialisation matérielle, etc., etc.
Joakim Koed

1
Merci d'avoir soumis le bogue, @RobertIanHawdon. Je me suis marqué comme affecté.
Joakim Koed

Réponses:


12

Il s'agit d'un bug connu. Essayez rmmod btusb ; modprobe btusb. J'ai dû le faire jusqu'à quatre fois.

J'ai vu cela avec mon Lenovo P50 avec Intel 8260 wifi / bluetooth. Parfois, le micrologiciel Bluetooth ne se charge pas correctement au démarrage. D'autres fois, cela ne fonctionne tout simplement pas.


2
Il y a eu de sérieuses régressions dans le support Bluetooth pour 16.04.
Amias

@Amias Eh bien, je ne pouvais pas non plus faire fonctionner Bluetooth en 14.04.
jarno

1
Fonctionne pour moi sur mon Lenovo Y510P exécutant 16.04. J'ai ajouté un alias à mon ~ / .bashrc:alias headphones='sudo rmmod btusb ; sudo modprobe btusb'
BenB

3

J'ai eu le même problème avec Jaybird X2 et Bluebuds X, bien que d'autres appareils audio Bluetooth aient fonctionné sans problème. Avec les écouteurs, j'ai eu cette erreur:

Assertion 'pa_channels_valid(channels)' failed at pulse/volume.c:74, function pa_cvolume_set(). Aborting.

et pulseaudio s'est écrasé. Ce qui a résolu l'installation de pulseaudio à partir de sources:

  • Installez tous les packages requis: sudo apt-get build-dep pulseaudio
  • Téléchargez https://freedesktop.org/software/pulseaudio/releases/pulseaudio-9.0.tar.gz et décompressez.
  • Dans la source dir, exécutez: ./bootstrap.sh --prefix=/usr. Si vous le souhaitez, vous pouvez modifier la CFLAGSvariable pour activer les optimisations du compilateur, par exemple utiliser -O2au lieu de -O0.
  • Ensuite, makeetsudo make install

Cela écrasera l'installation système par défaut, mais cela fonctionnera jusqu'à ce que les packages soient mis à jour. Pour éviter les mises à jour, nous pouvons mettre les packages pulseaudio en attente:

sudo apt-mark hold libpulse-dev libpulse0 libpulse-mainloop-glib0 pulseaudio pulseaudio-module-bluetooth pulseaudio-utils libpulsedsp pulseaudio-module-x11

Notez que j'ai installé pulseaudio 9.0, mais ce n'est pas la version qui l'a fait fonctionner. J'ai essayé d'utiliser la version packagée de pulseaudio 9.0 du PPA , mais elle s'est également bloquée avec la même erreur.


Salut. Est-ce que cela compile également toutes les décences? En fait, je suis juste passé à 6 de rusé hier. Fonctionne parfaitement.
Joakim Koed

Il n'y a eu aucun problème avec la compilation. Que voulez-vous dire?
Andrzej Pronobis

Si ce n'est pas la version, qu'est-ce qui a fait la différence?
Daniel Szmulewicz

2

J'ai eu ce problème avec mon casque Bluedio T + 3 et ce qui se passe, je pense, c'est qu'il y a un délai de connexion. Vous devez décommenter la ligne ; exit-idle-time = 20du fichier /etc/pulse/daemon.confen supprimant le point-virgule (;).

Modifiez la valeur -1pour devenir:

exit-idle-time = -1

Après cela, utilisez à bluetoothctlnouveau pour essayer de vous connecter à l'appareil. Voir ici pour les instructions:

Arch Wiki: casque Bluetooth


1

Vérifiez les points suivants:

  • Jaybird X2 est couplé
  • il est marqué comme approuvé (via bluetoothctlet trust XX:XX:XX:XX(où XX:XX:XX:XXest l'adresse MAC de votre Jaybird) ou via blueman-manager)
  • il est allumé

Appuyez une fois sur le bouton d'alimentation de votre Jaybird X2. Cela déclenche probablement une connexion automatique aux appareils connus. Vous devrez donc peut-être vous assurer que d'autres appareils n'interfèrent pas ici. Dès lors, la connexion était stable et elle se connecte également automatiquement après un redémarrage.

Faites-moi savoir si cela a également résolu votre problème. J'ai aussi fait beaucoup d'autres choses et j'ai failli abandonner, quand j'ai accidentellement appuyé sur le bouton d'alimentation ;-) Il se pourrait donc aussi que l'une de ces autres choses ait résolu le problème. (cherchait déjà et essayait des choses autour de bluetooth, pulseaudio, bluez, pactl load-module peu importe; j'ai donc encore beaucoup d'autres astuces :-D)

MISE À JOUR (après avoir à nouveau rencontré des problèmes de connexion)

Après avoir connecté Jaybird X2 à mon téléphone Android, je n'ai pas pu me reconnecter à mon ordinateur portable, même après avoir interrompu la connexion depuis mon téléphone Android. Je ne sais pas encore, quel est exactement le problème ici, mais pour rétablir la connexion, j'ai dû faire ce qui suit:

  1. déconnecter Jaybird X2 de mon téléphone Android (ou de tout autre appareil)
  2. redémarrer Ubuntu
  3. la reconnexion fonctionne et la connexion est stable (cela ne fonctionnait généralement pas lors du premier appairage ... J'ai également eu besoin d'un redémarrage après cela)

J'ai également essayé d'autres choses et il semble qu'au moins pulseaudio-module-bluetoothsoit nécessaire. La configuration de coexistence wifi / bluetooth est également requise au moins sur ma machine (voir: /ubuntu//a/645072/558838 ). Et enfin et surtout: un redémarrage est toujours nécessaire pour rétablir la connexion au cas où je passerais à un autre appareil.

Pour résumer: avec cette étape de redémarrage, je suis capable de reconnecter le Jaybird X2 avec succès et la connexion est stable. Si quelqu'un connaît un moyen plus simple d'omettre l'étape de redémarrage, veuillez contribuer :) /etc/init.d/bluetooth restartne suffit pas.

(étapes supplémentaires que j'ai essayées):

J'ai regardé mon histoire. J'ai également essayé ce qui suit où l'un ou l'autre aurait pu contribuer à la solution ci-dessus:

  • apt-get install pulseaudio-module-bluetooth (sur mon système, il n'était pas installé)
  • les journaux ont mentionné quelque chose de manquant ofono, donc j'ai également installé
  • a fait un sudo chown -R $USER ~/*
  • également appliqué: /ubuntu//a/691299/558838 (Cependant, je l'ai annulé car cela n'a pas aidé. Mais il était peut-être encore actif lorsque j'ai essayé la connexion automatique)
  • a également purgé / installé le pack pulseaudio, blueman, bluetooth

Merci d'avoir essayé d'aider, venez de le tester, plantez dès que j'ai essayé. J'ai ensuite essayé: pactl load-module module-bluetooth-discovery et appuyez à nouveau sur power, il s'est de nouveau écrasé pulseaudio: /
Joakim Koed

Ajout d'étapes supplémentaires à la réponse, que j'ai essayées. Si vous avez besoin de détails sur l'un d'entre eux, demandez-le.
Roland

D'ACCORD. J'ai découvert autre chose aujourd'hui: après un sommeil, je ne pouvais plus le faire fonctionner. Cela fonctionne toujours après un redémarrage. Pire encore: dès que la connexion Bluetooth est établie, ma connexion sans fil ne fonctionne plus. Il reste connecté mais ne transfère rien. Je dois approfondir celui-là.
Roland

N'hésitez pas à vous marquer comme affecté: bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1574324
Joakim Koed

J'ai résolu le problème de coexistence wifi / bluetooth avec ce qui suit: askubuntu.com/a/645072/558838 :) Je me suis de nouveau endormi et il a récupéré la connexion bluetooth ... donc je devrai peut-être vérifier ce que j'ai fait d'autre, afin que ça marche maintenant ... Peut-être que le bug de coexistence était aussi le problème pour la connexion stable? Au moins, cela semble plus raisonnable que les autres choses que j'ai énumérées :-) Pourriez-vous essayer celle-là aussi?
Roland

1

Exécutez le script ici sur GitHub

Et le problème disparaîtra.

#! /usr/bin/env python3.5
"""

Fixing bluetooth stereo headphone/headset problem in ubuntu 16.04 and also debian jessie, with bluez5.

Workaround for bug: https://bugs.launchpad.net/ubuntu/+source/indicator-sound/+bug/1577197
Run it with python3.5 or higher after pairing/connecting the bluetooth stereo headphone.

This will be only fixes the bluez5 problem mentioned above .

Licence: Freeware

See ``python3.5 a2dp.py -h``.

Shorthands:

    $ alias speakers="a2dp.py 10:08:C1:44:AE:BC"
    $ alias headphones="a2dp.py 00:22:37:3D:DA:50"
    $ alias headset="a2dp.py 00:22:37:F8:A0:77 -p hsp"

    $ speakers



Check here for the latest updates: https://gist.github.com/pylover/d68be364adac5f946887b85e6ed6e7ae

Thanks to:

 * https://github.com/DominicWatson, for adding the ``-p/--profile`` argument.
 * https://github.com/IzzySoft, for mentioning wait before connecting again.
 * https://github.com/AmploDev, for v0.4.0

Change Log
----------

- 0.4.1
  * Sorting device list

- 0.4.0
  * Adding ignore_fail argument by @AmploDev.
  * Sending all available streams into selected sink, after successfull connection by @AmploDev.

- 0.3.3
  * Updating default sink before turning to ``off`` profile.

- 0.3.2
  * Waiting a bit: ``-w/--wait`` before connecting again.

- 0.3.0
  * Adding -p / --profile option for using the same script to switch between headset and A2DP audio profiles

- 0.2.5
  * Mentioning [mac] argument.

- 0.2.4
  * Removing duplicated devices in select device list.

- 0.2.3
  * Matching ANSI escape characters. Tested on 16.10 & 16.04

- 0.2.2
  * Some sort of code enhancements.

- 0.2.0
  * Adding `-V/--version`, `-w/--wait` and `-t/--tries` CLI arguments.

- 0.1.1
  * Supporting the `[NEW]` prefix for devices & controllers as advised by @wdullaer
  * Drying the code.

"""

import sys
import re
import asyncio
import subprocess as sb
import argparse


__version__ = '0.4.0'


HEX_DIGIT_PATTERN = '[0-9A-F]'
HEX_BYTE_PATTERN = '%s{2}' % HEX_DIGIT_PATTERN
MAC_ADDRESS_PATTERN = ':'.join((HEX_BYTE_PATTERN, ) * 6)
DEVICE_PATTERN = re.compile('^(?:.*\s)?Device\s(?P<mac>%s)\s(?P<name>.*)' % MAC_ADDRESS_PATTERN)
CONTROLLER_PATTERN = re.compile('^(?:.*\s)?Controller\s(?P<mac>%s)\s(?P<name>.*)' % MAC_ADDRESS_PATTERN)
WAIT_TIME = .75
TRIES = 4
PROFILE = 'a2dp'


_profiles = {
    'a2dp': 'a2dp_sink',
    'hsp': 'headset_head_unit',
    'off': 'off'
}

# CLI Arguments
parser = argparse.ArgumentParser(prog=sys.argv[0])
parser.add_argument('-e', '--echo', action='store_true', default=False,
                    help='If given, the subprocess stdout will be also printed on stdout.')
parser.add_argument('-w', '--wait', default=WAIT_TIME, type=float,
                    help='The seconds to wait for subprocess output, default is: %s' % WAIT_TIME)
parser.add_argument('-t', '--tries', default=TRIES, type=int,
                    help='The number of tries if subprocess is failed. default is: %s' % TRIES)
parser.add_argument('-p', '--profile', default=PROFILE,
                    help='The profile to switch to. available options are: hsp, a2dp. default is: %s' % PROFILE)
parser.add_argument('-V', '--version', action='store_true', help='Show the version.')
parser.add_argument('mac', nargs='?', default=None)


# Exceptions
class SubprocessError(Exception):
    pass


class RetryExceededError(Exception):
    pass


class BluetoothctlProtocol(asyncio.SubprocessProtocol):
    def __init__(self, exit_future, echo=True):
        self.exit_future = exit_future
        self.transport = None
        self.output = None
        self.echo = echo

    def listen_output(self):
        self.output = ''

    def not_listen_output(self):
        self.output = None

    def pipe_data_received(self, fd, raw):
        d = raw.decode()
        if self.echo:
            print(d, end='')

        if self.output is not None:
            self.output += d

    def process_exited(self):
        self.exit_future.set_result(True)

    def connection_made(self, transport):
        self.transport = transport
        print('Connection MADE')

    async def send_command(self, c):
        stdin_transport = self.transport.get_pipe_transport(0)
        # noinspection PyProtectedMember
        stdin_transport._pipe.write(('%s\n' % c).encode())

    async def search_in_output(self, expression, fail_expression=None):
        if self.output is None:
            return None

        for l in self.output.splitlines():
            if fail_expression and re.search(fail_expression, l, re.IGNORECASE):
                raise SubprocessError('Expression "%s" failed with fail pattern: "%s"' % (l, fail_expression))

            if re.search(expression, l, re.IGNORECASE):
                return True

    async def send_and_wait(self, cmd, wait_expression, fail_expression='fail'):
        try:
            self.listen_output()
            await self.send_command(cmd)
            while not await self.search_in_output(wait_expression.lower(), fail_expression=fail_expression):
                await wait()
        finally:
            self.not_listen_output()

    async def disconnect(self, mac):
        print('Disconnecting the device.')
        await self.send_and_wait('disconnect %s' % ':'.join(mac), 'Successful disconnected')

    async def connect(self, mac):
        print('Connecting again.')
        await self.send_and_wait('connect %s' % ':'.join(mac), 'Connection successful')

    async def trust(self, mac):
        await self.send_and_wait('trust %s' % ':'.join(mac), 'trust succeeded')

    async def quit(self):
        await self.send_command('quit')

    async def get_list(self, command, pattern):
        result = set()
        try:
            self.listen_output()
            await self.send_command(command)
            await wait()
            for l in self.output.splitlines():
                m = pattern.match(l)
                if m:
                    result.add(m.groups())
            return sorted(list(result), key=lambda i: i[1])
        finally:
            self.not_listen_output()

    async def list_devices(self):
        return await self.get_list('devices', DEVICE_PATTERN)

    async def list_paired_devices(self):
        return await self.get_list('paired-devices', DEVICE_PATTERN)

    async def list_controllers(self):
        return await self.get_list('list', CONTROLLER_PATTERN)

    async def select_paired_device(self):
        print('Selecting device:')
        devices = await self.list_paired_devices()
        count = len(devices)

        if count < 1:
            raise SubprocessError('There is no connected device.')
        elif count == 1:
            return devices[0]

        for i, d in enumerate(devices):
            print('%d. %s %s' % (i+1, d[0], d[1]))
        print('Select device[1]:')
        selected = input()
        return devices[0 if not selected.strip() else (int(selected) - 1)]


async def wait():
    return await asyncio.sleep(WAIT_TIME)


async def execute_command(cmd, ignore_fail=False):
    p = await asyncio.create_subprocess_shell(cmd, stdout=sb.PIPE, stderr=sb.PIPE)
    stdout, stderr = await p.communicate()
    stdout, stderr = \
        stdout.decode() if stdout is not None else '', \
        stderr.decode() if stderr is not None else ''
    if p.returncode != 0 or stderr.strip() != '':
        message = 'Command: %s failed with status: %s\nstderr: %s' % (cmd, p.returncode, stderr)
        if ignore_fail:
            print('Ignoring: %s' % message)
        else:
            raise SubprocessError(message)
    return stdout


async def execute_find(cmd, pattern, tries=0, fail_safe=False):
    tries = tries or TRIES

    message = 'Cannot find `%s` using `%s`.' % (pattern, cmd)
    retry_message = message + ' Retrying %d more times'
    while True:
        stdout = await execute_command(cmd)
        match = re.search(pattern, stdout)

        if match:
            return match.group()
        elif tries > 0:
            await wait()
            print(retry_message % tries)
            tries -= 1
            continue

        if fail_safe:
            return None

        raise RetryExceededError('Retry times exceeded: %s' % message)


async def find_dev_id(mac, **kw):
    return await execute_find('pactl list cards short', 'bluez_card.%s' % '_'.join(mac), **kw)


async def find_sink(mac, **kw):
    return await execute_find('pacmd list-sinks', 'bluez_sink.%s' % '_'.join(mac), **kw)


async def set_profile(device_id, profile):
    print('Setting the %s profile' % profile)
    try:
        return await execute_command('pactl set-card-profile %s %s' % (device_id, _profiles[profile]))
    except KeyError:
        print('Invalid profile: %s, please select one one of a2dp or hsp.' % profile, file=sys.stderr)
        raise SystemExit(1)


async def set_default_sink(sink):
    print('Updating default sink to %s' % sink)
    return await execute_command('pacmd set-default-sink %s' % sink)


async def move_streams_to_sink(sink):
    streams = await execute_command('pacmd list-sink-inputs | grep "index:"', True)
    for i in streams.split():
        i = ''.join(n for n in i if n.isdigit())
        if i != '':
            print('Moving stream %s to sink' % i)
            await execute_command('pacmd move-sink-input %s %s' % (i, sink))
    return sink


async def main(args):
    global WAIT_TIME, TRIES

    if args.version:
        print(__version__)
        return 0

    mac = args.mac

    # Hacking, Changing the constants!
    WAIT_TIME = args.wait
    TRIES = args.tries

    exit_future = asyncio.Future()
    transport, protocol = await asyncio.get_event_loop().subprocess_exec(
        lambda: BluetoothctlProtocol(exit_future, echo=args.echo), 'bluetoothctl'
    )

    try:

        if mac is None:
            mac, _ = await protocol.select_paired_device()

        mac = mac.split(':' if ':' in mac else '_')
        print('Device MAC: %s' % ':'.join(mac))

        device_id = await find_dev_id(mac, fail_safe=True)
        if device_id is None:
            print('It seems device: %s is not connected yet, trying to connect.' % ':'.join(mac))
            await protocol.trust(mac)
            await protocol.connect(mac)
            device_id = await find_dev_id(mac)

        sink = await find_sink(mac, fail_safe=True)
        if sink is None:
            await set_profile(device_id, args.profile)
            sink = await find_sink(mac)

        print('Device ID: %s' % device_id)
        print('Sink: %s' % sink)

        await set_default_sink(sink)
        await wait()

        await set_profile(device_id, 'off')

        if args.profile is 'a2dp':
            await protocol.disconnect(mac)
            await wait()
            await protocol.connect(mac)

        device_id = await find_dev_id(mac)
        print('Device ID: %s' % device_id)

        await set_profile(device_id, args.profile)
        await set_default_sink(sink)
        await move_streams_to_sink(sink)

    except (SubprocessError, RetryExceededError) as ex:
        print(str(ex), file=sys.stderr)
        return 1
    finally:
        print('Exiting bluetoothctl')
        await protocol.quit()
        await exit_future

        # Close the stdout pipe
        transport.close()

    if args.profile == 'a2dp':
        print('"Enjoy" the HiFi stereo music :)')
    else:
        print('"Enjoy" your headset audio :)')


if __name__ == '__main__':
    sys.exit(asyncio.get_event_loop().run_until_complete(main(parser.parse_args())))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.