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), він париться, з'єднується на дві секунди, після чого відключається.

Журнал форми журналу (з мого робочого столу з оператором 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, виявляти і я повинен 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 wifi / bluetooth. Іноді прошивка Bluetooth не завантажується правильно під час завантаження. В інших випадках це просто не працює.


2
У сервісі Bluetooth підтримано 16.04 серйозні регресії.
Амія

@Amias Ну, я також не міг змусити роботу Bluetooth через 14.04.
jarno

1
Підходить для мене на моєму Lenovo Y510P, який працює 16.04. Я додав псевдонім до мого ~ / .bashrc:alias headphones='sudo rmmod btusb ; sudo modprobe btusb'
БенБ

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: гарнітура Bluetooth


1

Переконайтесь у наступному:

  • Jaybird X2 є парним
  • він позначений як довірений (або через bluetoothctlі trust XX:XX:XX:XX(де XX:XX:XX:XXMAC-адреса вашого Jaybird) або через blueman-manager)
  • він увімкнено

Натисніть кнопку живлення вашого Jaybird X2 один раз. Це, ймовірно, запускає автоматичне підключення до відомих пристроїв. Тому вам може знадобитися переконатися, що інші пристрої тут не заважають. Відтоді з'єднання було стабільним, і воно також підключається автоматично після перезавантаження.

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

ОНОВЛЕННЯ (після виникнення проблем із підключенням)

Після того, як я підключив Jaybird X2 до телефону з Android, я не зміг знову підключитися до свого ноутбука, навіть після того, як я скинув з'єднання зі свого Android-телефону. Ще не знаю, у чому саме проблема тут, але щоб повернути з'єднання, мені довелося зробити наступне:

  1. відключити Jaybird X2 від телефону з Android (або будь-якого іншого пристрою)
  2. перезавантажити ubuntu
  3. відновлюється робота, і з'єднання стабільне (зазвичай це не спрацьовувало при першому спарюванні ... Я також вимагав перезавантаження після цього)

Я також спробував деякі інші речі і, здається, що pulseaudio-module-bluetoothпотрібно, принаймні . Також необхідна конфігурація співіснування wifi / bluetooth принаймні на моїй машині (див .: /ubuntu//a/645072/558838 ). І останнє, але не менш важливе: для відновлення з'єднання завжди потрібна перезавантаження, якщо я перейшов на інший пристрій.

Підводячи підсумок: за допомогою цього етапу перезавантаження я можу успішно підключити Jaybird X2, і зв’язок стабільний. Якщо хтось знає простіший спосіб пропустити крок перезавантаження, будь ласка, зробіть свій внесок :) /etc/init.d/bluetooth restartнедостатньо.

(додаткові кроки, які я спробував):

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

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

Дякую за те, що намагаєтесь допомогти, просто перевірили, збивайтеся, як тільки я спробував. Потім я спробував: модуль завантаження модуля pactl-bluetooth-виявити і знову натиснути живлення, він знову зазнав аварії pulseaudio: /
Joakim Koed

Додав додаткові кроки до відповіді, які я спробував. Якщо вам потрібні деталі про будь-яку, просто запитайте.
Roland

ДОБРЕ. Сьогодні я дізнався щось інше: після сну я не зміг змусити його знову працювати. Він все ще працює після перезавантаження. Ще гірше: як тільки встановлено з'єднання Bluetooth, моє бездротове з'єднання більше не працює. Він залишається на зв’язку, але нічого не передає. Я маю дослідити це ще.
Роланд

Сміливо позначте себе як постраждалого: bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1574324
Йоаким Коед

Я вирішив проблему співіснування через 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.