16.04 No se pueden usar auriculares bluetooth A2DP, se empareja pero no se conecta. Registros dentro

15

Primero, intenté seguir ambos: https://vilimpoc.org/blog/2016/04/30/ubuntu-16-04-bluetooth-speakers/ y PulseAudio no puede cargar el módulo bluetooth 15.10 / 16.04 / 16.10

Cuando trato de conectar mi Jaybird X2 (probado en computadoras de escritorio y portátiles, broadcom e intel) se empareja, se conecta durante dos segundos y luego se desconecta.

Registro de syslog (desde mi escritorio con 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.

Y otras veces:

a2dp-sink profile connect failed for xxxxxxx Protocol not available

EDITAR .. IMPORTANTE:

Ahora descubrí que intentar conectarme a otros dispositivos funciona bien (Micropod BT y Samsung AirTrack) la mayor parte del tiempo, pero tan pronto como pruebo Jaybird X2, deshabilita / descarga module-bluetooth-discover y tengo que hacerlo pactl load-module module-bluetooth-discoverpor el otros dos para funcionar de nuevo ..

Ahora esto sucede con la computadora portátil:

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.

Pude conectarlo brevemente en mi escritorio antes, pero A2DP no funcionaba la mayor parte del tiempo.

Dos errores diferentes pero el mismo problema. Que esta pasando?

¿Está bluetooth roto en Ubuntu 16.04? Funciona en Windows y con mi teléfono Android.

¡Cualquier ayuda sería increíble! :) De alguna manera logré hacerlo funcionar brevemente, primero funcionó, luego A2DP no funcionó ... así que sospecho que esto tiene algo que ver con A2DP. No estoy seguro.

Joakim Koed
fuente
¿Puso sus auriculares en modo de emparejamiento antes de conectarse? Desde el dispositivo apagado, mantenga presionada la tecla central durante 4 s hasta que se enciendan las luces rojas / verdes. Búscalo en Ubuntu y conéctate. Ver askubuntu.com/questions/259354/…
Takkat
Sí, y se empareja bien. El problema no es el emparejamiento, sino la "conexión". Se conecta y dice "auriculares conectados" y luego se desconecta 2 segundos después.
Joakim Koed
Solo pregunto porque es un síntoma de que los dispositivos no emparejados correctamente parecen conectarse pero luego fallan. Puede valer la pena volver a intentarlo (después de eliminar el dispositivo de dispositivos conocidos).
Takkat
Takket: Probablemente lo he hecho 20 veces. auriculares con restablecimiento
completo
1
Gracias por enviar el error, @RobertIanHawdon. Me he marcado como afectado.
Joakim Koed

Respuestas:

12

Es un error conocido. Tratar rmmod btusb ; modprobe btusb. He tenido que hacerlo hasta cuatro veces.

He visto esto con mi Lenovo P50 con Intel 8260 wifi / bluetooth. A veces, el firmware del bluetooth no se carga correctamente en el arranque. Otras veces simplemente no funciona.

user550672
fuente
2
Ha habido algunas regresiones serias en el soporte de Bluetooth para 16.04.
Amias
@Amias Bueno, tampoco pude hacer que Bluetooth funcionara en 14.04.
jarno
1
Funciona para mí en mi Lenovo Y510P con 16.04. He agregado un alias a mi ~ / .bashrc:alias headphones='sudo rmmod btusb ; sudo modprobe btusb'
BenB
3

He tenido el mismo problema con Jaybird X2 y Bluebuds X, aunque otros dispositivos de audio Bluetooth funcionaron sin problemas. Con los auriculares, recibí este error:

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

y pulseaudio se estrelló. Lo que resolvió fue instalar pulseaudio desde las fuentes:

  • Instale todos los paquetes requeridos: sudo apt-get build-dep pulseaudio
  • Descargue https://freedesktop.org/software/pulseaudio/releases/pulseaudio-9.0.tar.gz y desempaquete.
  • En el directorio de fuentes, ejecute: ./bootstrap.sh --prefix=/usr. Si lo desea, puede cambiar la CFLAGSvariable para habilitar las optimizaciones del compilador, por ejemplo, usar en -O2lugar de -O0.
  • Entonces makeysudo make install

Esto sobrescribirá la instalación predeterminada del sistema, pero funcionará hasta que se actualicen los paquetes. Para evitar actualizaciones, podemos poner los paquetes de pulseaudio en espera:

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

Tenga en cuenta que instalé pulseaudio 9.0, pero no es la versión que lo hizo funcionar. Intenté usar la versión empaquetada de pulseaudio 9.0 del PPA , pero también falló con el mismo error.

Andrzej Pronobis
fuente
Hola. ¿Eso compila todas las deficiencias también? De hecho, acabo de bajar a 6 desde ayer astuto. Funcionó perfectamente.
Joakim Koed
No hubo problemas con la compilación. ¿Qué quieres decir?
Andrzej Pronobis
Si no es la versión, ¿qué hizo la diferencia?
Daniel Szmulewicz
2

Tuve este problema con mi auricular Bluedio T + 3 y lo que creo que está sucediendo es que hay un tiempo de espera de conexión. Necesitas descomentar la línea; exit-idle-time = 20 en el archivo /etc/pulse/daemon.confeliminando el punto y coma (;).

Cambie el valor -1para convertirse en:

exit-idle-time = -1

Después de eso, use bluetoothctlnuevamente para intentar conectarse al dispositivo. Consulte aquí para obtener instrucciones:

Arch wiki: auriculares bluetooth

anandan111
fuente
1

Asegúrese de lo siguiente:

  • Jaybird X2 está emparejado
  • está marcado como confiable (ya sea a través de bluetoothctly trust XX:XX:XX:XX(donde XX:XX:XX:XXestá la dirección MAC de su Jaybird) o a través deblueman-manager )
  • está encendido

Presione el botón de encendido de su Jaybird X2 una vez. Esto probablemente desencadena una conexión automática a dispositivos conocidos. Por lo tanto, es posible que deba asegurarse de que otros dispositivos no interfieran aquí. A partir de entonces, la conexión fue estable y también se conecta automáticamente después de un reinicio.

Avísame si esto también resolvió tu problema. También hice muchas otras cosas y casi me rendí, cuando accidentalmente presioné el botón de encendido ;-) Así que también podría ser que una de esas otras cosas resolvió el problema. (ya estaba buscando y probando cosas sobre bluetooth, pulseaudio, bluez, pactl load-module lo que sea; así que todavía tengo muchas otras sugerencias :-D)

ACTUALIZACIÓN (después de tener problemas de conexión nuevamente)

Después de conectar Jaybird X2 a mi teléfono Android, no pude volver a conectarme a mi computadora portátil, incluso después de haber desconectado la conexión de mi teléfono Android. Todavía no sé cuál es exactamente el problema aquí, pero para recuperar la conexión, tuve que hacer lo siguiente:

  1. desconectar Jaybird X2 de mi teléfono Android (o cualquier otro dispositivo)
  2. reiniciar ubuntu
  3. la reconexión funciona y la conexión es estable (por lo general, no funcionó cuando se emparejó por primera vez ... También necesité reiniciar después de eso)

También probé algunas otras cosas y parece que al menos pulseaudio-module-bluetoothes obligatorio. Además, la configuración de coexistencia wifi / bluetooth se requiere al menos en mi máquina (consulte: /ubuntu//a/645072/558838 ). Y por último, pero no menos importante: siempre es necesario reiniciar para recuperar la conexión en caso de que cambie a otro dispositivo.

Para resumir: con ese paso de reinicio puedo volver a conectar el Jaybird X2 con éxito y la conexión es estable. Si alguien conoce una forma más fácil de omitir el paso de reinicio, contribuya :) /etc/init.d/bluetooth restartno es suficiente.

(pasos adicionales que he probado):

Miré en mi historia. Intenté también lo siguiente, donde uno u otro podría haber contribuido a la solución anterior:

  • apt-get install pulseaudio-module-bluetooth (en mi sistema no estaba instalado)
  • los registros mencionaron algo sobre la falta ofono, así que también instalé eso
  • hizo un sudo chown -R $USER ~/*
  • también aplicado: /ubuntu//a/691299/558838 (Sin embargo, lo revertí porque no ayudó. Pero aún podría haber estado activo, cuando probé la conexión automática)
  • también purgó / instaló el paquete de pulseaudio, blueman, bluetooth
Roland
fuente
Gracias por intentar ayudar, solo lo probé, colapsé tan pronto como lo intenté. Luego intenté: pactl load-module module-bluetooth-discover y presionar power nuevamente, una vez más se bloqueó pulseaudio: /
Joakim Koed
Se agregaron pasos adicionales a la respuesta, que he probado. Si necesita detalles sobre alguno, solo pregunte.
Roland
OKAY. Hoy descubrí algo más: después de dormir no pude hacerlo funcionar de nuevo. Aún funciona después de un reinicio. Peor aún: tan pronto como se establece la conexión Bluetooth, mi conexión inalámbrica ya no funciona. Permanece conectado pero no transfiere nada. Tengo que investigar eso más a fondo.
Roland
Siéntase libre de marcarnos
Joakim Koed
Solucioné el problema de coexistencia wifi / bluetooth con lo siguiente: askubuntu.com/a/645072/558838 :) Dormí nuevamente y recuperé la conexión bluetooth ... así que quizás tenga que verificar qué más hice, para que ahora funciona ... ¿Quizás el error de coexistencia también fue el problema para la conexión estable? Al menos suena más razonable que las otras cosas que he enumerado :-) ¿Podrías probar eso también?
Roland
1

Ejecute el script aquí en GitHub

Y el problema desaparecerá.

#! /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())))
bikashg
fuente