16.04 Не могу использовать Bluetooth A2DP наушники, но не подключается. Логи внутри


15

Во-первых, я попробовал выполнить следующие действия: https://vilimpoc.org/blog/2016/04/30/ubuntu-16-04-bluetooth-speakers/, а PulseAudio не может загрузить модуль Bluetooth 15.10 / 16.04 / 16.10

Когда я пытаюсь подключить свой Jaybird X2 (как на настольном компьютере, так и на ноутбуке, Broadcom и Intel), он подключается, подключается в течение двух секунд, а затем отключается.

Форма журнала syslog (с моего рабочего стола с 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.

И другие времена:

a2dp-sink profile connect failed for xxxxxxx Protocol not available

РЕДАКТИРОВАТЬ .. ВАЖНО:

Теперь я обнаружил, что попытки подключения к другим устройствам работают нормально (Micropod BT и Samsung AirTrack) большую часть времени, но как только я пробую Jaybird X2, он отключает / выгружает модуль-bluetooth-Discover, и мне нужно pactl load-module module-bluetooth-discoverдля другие два, чтобы функционировать снова ..

Теперь это происходит с ноутбуком:

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.

Я кратко смог подключить его на своем рабочем столе раньше, но A2DP не работал большую часть времени ..

Две разные ошибки, но одна и та же проблема. Что здесь происходит?

Bluetooth просто сломан в Ubuntu 16.04? Он работает в Windows и на моем телефоне Android.

Любая помощь будет потрясающей! :) Мне как-то удалось сделать это на короткое время, сначала это работало, затем A2DP не работало .. поэтому я подозреваю, что это как-то связано с A2DP. Точно сказать не могу.


Вы подключили гарнитуру в режим сопряжения перед подключением? От выключенного устройства нажмите и удерживайте центральную кнопку в течение 4 секунд, пока не начнут мигать красные / зеленые огни. Ищите его в Ubuntu и подключайтесь. См. Askubuntu.com/questions/259354/…
Таккат

Да, и это просто пара. Проблема не в том, чтобы очистить, а "подключается" .. Он подключается и говорит "наушники подключены", а затем отключается через 2 секунды.
Йоаким Коед

Просто спрашиваю, потому что это признак не правильно спаренных устройств, которые появляются, чтобы соединиться, но затем перестают работать. Возможно, стоит повторить попытку (после удаления устройства из известных устройств).
Таккат

Таккет: Я, вероятно, сделал это 20 раз. гарнитура с жестким сбросом и т. д. и т. д.
Йоаким Коед

1
Спасибо за сообщение об ошибке, @RobertIanHawdon. Я отметил себя как пострадавший.
Йоаким Коед

Ответы:


12

Это известная ошибка. Попробуй rmmod btusb ; modprobe btusb. Я должен был сделать это до четырех раз.

Я видел это с моим Lenovo P50 с Intel 8260 Wi-Fi / Bluetooth. Иногда микропрограмма Bluetooth не загружается правильно при загрузке. В других случаях это просто не работает.


2
В 16.04 произошла серьезная регрессия в поддержке Bluetooth.
Amias

@ Amias Ну, я не смог заставить работать bluetooth в 14.04.
Ярно

1
У меня работает на моем Lenovo Y510P под управлением 16.04. Я добавил псевдоним в мой ~ / .bashrc:alias headphones='sudo rmmod btusb ; sudo modprobe btusb'
BenB

3

У меня была такая же проблема с Jaybird X2 и Bluebuds X, хотя другие аудиоустройства Bluetooth работали без проблем. С наушниками я получил эту ошибку:

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

и пульсаудио разбился. То, что решило это, установило pulseaudio из источников:

  • Установите все необходимые пакеты: sudo apt-get build-dep pulseaudio
  • Загрузите https://freedesktop.org/software/pulseaudio/releases/pulseaudio-9.0.tar.gz и распакуйте.
  • В исходном директории, запустите: ./bootstrap.sh --prefix=/usr. Если вы хотите, вы можете изменить CFLAGSпеременную, чтобы включить оптимизацию компилятора, например, использовать -O2вместо -O0.
  • Тогда makeиsudo make install

Это перезапишет установку системы по умолчанию, но будет работать до обновления пакетов. Чтобы предотвратить обновления, мы можем приостановить пакеты pulseaudio:

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

Обратите внимание, что я установил pulseaudio 9.0, но это не та версия, которая заставила его работать. Я пытался использовать упакованную версию pulseaudio 9.0 от PPA , но она также вылетала с той же ошибкой.


Здравствуй. Это также составляет все приличия? Я на самом деле только что понизился до 6 с коварного вчера. Работал отлично.
Иоаким Коед

Проблем с компиляцией не было. Что вы имеете в виду?
Анджей Пронобис

Если не версия, в чем разница?
Даниэль Шмулевич

2

У меня была эта проблема с моей гарнитурой Bluedio T + 3, и я думаю, что произошел тайм-аут соединения. Вам необходимо раскомментировать строку ; exit-idle-time = 20в файле /etc/pulse/daemon.conf, удалив точку с запятой (;).

Измените значение на -1:

exit-idle-time = -1

После этого используйте bluetoothctlснова, чтобы попытаться подключиться к устройству. Смотрите здесь для получения инструкций:

Arch wiki: блютуз гарнитура


1

Убедитесь в следующем:

  • Jaybird X2 в паре
  • он помечается как доверенный (либо через bluetoothctlи trust XX:XX:XX:XX(где XX:XX:XX:XXнаходится MAC-адрес вашего Jaybird), либо через blueman-manager)
  • он включен

Нажмите кнопку питания вашего Jaybird X2 один раз. Это, вероятно, вызывает автоматическое подключение к известным устройствам. Таким образом, вам может потребоваться убедиться, что другие устройства здесь не мешают. С тех пор соединение было стабильным, и оно также подключается автоматически после перезагрузки.

Дайте мне знать, это также решило вашу проблему. Я также сделал много других вещей и почти сдался, когда я случайно нажал кнопку питания ;-) Так что, возможно, что одна из этих вещей решила проблему. (уже искал и пробовал что-то вокруг bluetooth, pulseaudio, bluez, pactl load-module, так что у меня есть еще много других советов :-D)

ОБНОВЛЕНИЕ (после проблем с подключением снова)

После того, как я подключил Jaybird X2 к своему телефону Android, я не смог снова подключиться к своему ноутбуку, даже после того, как у меня пропало соединение с телефона Android. Пока не знаю, в чем именно проблема, но чтобы восстановить соединение, мне пришлось сделать следующее:

  1. отключить Jaybird X2 от моего телефона Android (или любого другого устройства)
  2. перезагрузить убунту
  3. переподключение работает и соединение стабильно (обычно оно не работало при первом сопряжении ... Мне также потребовалась перезагрузка после этого)

Я также попробовал некоторые другие вещи, и кажется, что по крайней мере pulseaudio-module-bluetoothтребуется. Кроме того, конфигурация Wi-Fi / Bluetooth-совместимости требуется по крайней мере на моей машине (см .: /ubuntu//a/645072/558838 ). И последнее, но не менее важное: всегда требуется перезагрузка, чтобы восстановить соединение в случае, если я переключился на другое устройство.

Подводя итог: с этим шагом перезагрузки я могу успешно повторно подключить Jaybird X2, и соединение стабильно. Если кто-нибудь знает более простой способ пропустить шаг перезагрузки, пожалуйста, помогите :) /etc/init.d/bluetooth restartне достаточно.

(дополнительные шаги, которые я пробовал):

Я посмотрел в мою историю. Я также попробовал следующее, где один или другой могли бы внести свой вклад в решение выше:

  • apt-get install pulseaudio-module-bluetooth (в моей системе он не был установлен)
  • В журналах упоминается что-то о пропавших без вести ofono, поэтому я также установил, что
  • сделал sudo chown -R $USER ~/*
  • также применимо: /ubuntu//a/691299/558838 (Однако я отменил его, поскольку это не помогло. Но, возможно, он все еще был активен, когда я попытался автоматически подключиться)
  • также сделал чистку / установку pulseaudio, blueman, bluetooth packag

Спасибо за попытку помочь, только что проверил, сбой, как только я попытался. Затем я попытался: pactl load-module module-bluetooth-обнаружить и снова нажать кнопку питания, он снова разбился pulseaudio: /
Joakim Koed

Добавил дополнительные шаги к ответу, который я пробовал. Если вам нужны подробности, просто спросите.
Роланд

OK. Сегодня узнал что-то еще: после сна я не смог заставить его снова работать. Тем не менее он работает после перезагрузки. Еще хуже: как только соединение Bluetooth установлено, мое беспроводное соединение больше не работает. Он остается на связи, но ничего не передает. Я должен исследовать это дальше.
Роланд

Не стесняйтесь , чтобы отметить себя как пораженный: bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1574324
Йоаким Koed

Я исправил проблему сосуществования wifi / bluetooth следующим образом: askubuntu.com/a/645072/558838 :) Снова заснул и вернул соединение bluetooth ... так что, возможно, мне придется проверить, что еще я сделал, чтобы теперь это работает ... Может быть, ошибка сосуществования была также проблемой для стабильного соединения? По крайней мере, это звучит более разумно, чем другие вещи, которые я перечислил :-) Не могли бы вы попробовать это тоже?
Роланд

1

Запустите скрипт здесь на GitHub

И проблема исчезнет.

#! /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())))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.