16.04 Nie można używać słuchawek Bluetooth A2DP, paruje się, ale nie można się połączyć. Loguje się w środku

15

Najpierw próbowałem wykonać oba te: https://vilimpoc.org/blog/2016/04/30/ubuntu-16-04-bluetooth-speakers/ i PulseAudio nie może załadować modułu Bluetooth 15.10 / 16.04 / 16.10

Kiedy próbuję podłączyć Jaybird X2 (wypróbowany zarówno na komputerze stacjonarnym, jak i laptopie, urządzeniu Broadcom i Intel), łączy się w parę, łączy się na dwie sekundy, a następnie rozłącza się.

Zaloguj się do syslog (z mojego pulpitu z 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.

A innym razem:

a2dp-sink profile connect failed for xxxxxxx Protocol not available

EDYCJA .. WAŻNE:

Mam teraz okazało się, że próbuje się połączyć z innymi urządzeniami praca w porządku (Micropod BT i Samsung AirTrack) przez większość czasu, ale jak tylko próbuję jaybird X2, to wyłącza / i zwalniania modułu-bluetooth odkryć i muszę pactl load-module module-bluetooth-discoverdla pozostałe dwa będą działać ponownie ..

Teraz dzieje się tak z laptopem:

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.

Poprzednio byłem w stanie podłączyć go na pulpicie, ale A2DP przez większość czasu nie działał.

Dwa różne błędy, ale ten sam problem. Co się dzieje?

Czy w Ubuntu 16.04 jest po prostu zepsuty Bluetooth? Działa w systemie Windows i na moim telefonie z Androidem.

Każda pomoc byłaby niesamowita! :) Jakoś udało mi się sprawić, żeby działało krótko, najpierw działało, potem A2DP nie działało .. podejrzewam, że to ma coś wspólnego z A2DP. Niepewny.

Joakim Koed
źródło
Czy przełączyłeś zestaw słuchawkowy w tryb parowania przed połączeniem? Z wyłączonego urządzenia naciśnij i przytrzymaj środkowy klawisz przez 4 s, aż zacznie migać czerwona / zielona dioda. Wyszukaj go w Ubuntu i połącz. Zobacz askubuntu.com/questions/259354/…
Takkat
Tak, i paruje się dobrze. Problem nie polega na parowaniu, ale „podłączaniu”. Łączy się i mówi „słuchawki podłączone”, a następnie rozłącza się 2 sekundy później.
Joakim Koed
Tylko pytam, ponieważ jest to objaw nieprawidłowo sparowanych urządzeń, które wydają się łączyć, ale potem nie działają. Warto spróbować ponownie (po usunięciu urządzenia ze znanych urządzeń).
Takkat
Takket: Prawdopodobnie zrobiłem to 20 razy. twardy zestaw słuchawkowy itp. itp.
Joakim Koed
1
Dziękujemy za zgłoszenie błędu @RobertIanHawdon. Oznacziłem się jako dotknięty.
Joakim Koed

Odpowiedzi:

12

To znany błąd. Spróbować rmmod btusb ; modprobe btusb. Musiałem to zrobić nawet cztery razy.

Widziałem to z moim Lenovo P50 z Intel 8260 wifi / bluetooth. Czasami oprogramowanie układowe Bluetooth nie ładuje się poprawnie podczas rozruchu. Innym razem to po prostu nie działa.

użytkownik550672
źródło
2
Nastąpiły poważne regresje w zakresie obsługi Bluetooth dla 16.04.
Amias
@Amias Cóż, nie mogłem też sprawić, by Bluetooth działał w 14.04.
jarno
1
Działa dla mnie na moim Lenovo Y510P z 16.04. Dodałem alias do mojego ~ / .bashrc:alias headphones='sudo rmmod btusb ; sudo modprobe btusb'
BenB
3

Miałem ten sam problem z Jaybird X2 i Bluebuds X, chociaż inne urządzenia audio Bluetooth działały bez problemów. Ze słuchawkami dostałem ten błąd:

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

i pulseaudio rozbił się. Rozwiązaniem było zainstalowanie pulseaudio ze źródeł:

  • Zainstaluj wszystkie wymagane pakiety: sudo apt-get build-dep pulseaudio
  • Pobierz https://freedesktop.org/software/pulseaudio/releases/pulseaudio-9.0.tar.gz i rozpakuj.
  • W katalogu źródłowego, uruchom: ./bootstrap.sh --prefix=/usr. Jeśli chcesz, możesz zmienić CFLAGSzmienną, aby włączyć optymalizacje kompilatora, np. Użyj -O2zamiast -O0.
  • Następnie makeisudo make install

Spowoduje to zastąpienie domyślnej instalacji systemu, ale będzie działać do momentu aktualizacji pakietów. Aby zapobiec aktualizacjom, możemy zawiesić pakiety pulseaudio:

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

Zauważ , że zainstalowałem pulseaudio 9.0, ale nie jest to wersja, która sprawiła, że ​​działał. Próbowałem użyć spakowanej wersji pulseaudio 9.0 z PPA , ale również zawiesił się z tym samym błędem.

Andrzej Pronobis
źródło
Cześć. Czy to również kompiluje wszystkie przyzwoitości? Właśnie obniżyłem wczoraj do 6 z przebiegłego. Działał idealnie.
Joakim Koed
Nie było problemów z kompilacją. Co masz na myśli?
Andrzej Pronobis
Jeśli nie wersja, jaka to różnica?
Daniel Szmulewicz
2

Miałem ten problem z zestawem słuchawkowym Bluedio T + 3 i myślę, że dzieje się tak, że upłynął limit czasu połączenia. Musisz odkomentować wiersz ; exit-idle-time = 20w pliku /etc/pulse/daemon.conf, usuwając średnik (;).

Zmień wartość na -1:

exit-idle-time = -1

Następnie użyj bluetoothctlponownie, aby spróbować połączyć się z urządzeniem. Zobacz tutaj instrukcje:

Arch wiki: zestaw słuchawkowy Bluetooth

anandan111
źródło
1

Upewnij się, że:

  • Jaybird X2 jest sparowany
  • jest oznaczony jako zaufany (przez bluetoothctli trust XX:XX:XX:XX(gdzie XX:XX:XX:XXjest adres MAC twojego Jaybird) lub przez blueman-manager)
  • jest włączony

Naciśnij raz przycisk zasilania Jaybird X2. Prawdopodobnie powoduje to automatyczne połączenie ze znanymi urządzeniami. Może być więc konieczne upewnienie się, że inne urządzenia nie przeszkadzają tutaj. Od tego momentu połączenie było stabilne i łączy się automatycznie po ponownym uruchomieniu.

Daj mi znać, czy to również rozwiązało Twój problem. Zrobiłem też wiele innych rzeczy i prawie się poddałem, kiedy przypadkowo nacisnąłem przycisk zasilania ;-) Mogło być również, że jedna z tych rzeczy rozwiązała problem. (już szukałem i wypróbowywałem różne rzeczy wokół bluetooth, pulseaudio, bluez, pactl load-module cokolwiek; więc wciąż mam wiele innych wskazówek :-D)

AKTUALIZACJA (po ponownych problemach z połączeniem)

Po podłączeniu Jaybird X2 do mojego telefonu z Androidem nie byłem w stanie ponownie połączyć się z moim laptopem, nawet po zerwaniu połączenia z mojego telefonu z Androidem. Nie wiem jeszcze, na czym polega problem, ale aby odzyskać połączenie, musiałem wykonać następujące czynności:

  1. odłącz Jaybird X2 od mojego telefonu z Androidem (lub dowolnego innego urządzenia)
  2. uruchom ponownie Ubuntu
  3. ponowne połączenie działa, a połączenie jest stabilne (zwykle nie działało podczas parowania za pierwszym razem ... Wymagałem również ponownego uruchomienia)

Próbowałem też innych rzeczy i wydaje się, że przynajmniej pulseaudio-module-bluetoothjest to wymagane. Wymagana jest również konfiguracja współistnienia Wi-Fi / Bluetooth przynajmniej na moim komputerze (patrz: /ubuntu//a/645072/558838 ). I na koniec: ponowne uruchomienie jest zawsze wymagane, aby odzyskać połączenie w przypadku, gdy przełączyłem się na inne urządzenie.

Podsumowując: dzięki temu krokowi ponownego uruchomienia jestem w stanie pomyślnie połączyć Jaybird X2 i połączenie jest stabilne. Jeśli ktoś zna prostszy sposób na pominięcie kroku ponownego uruchomienia, prosimy o przekazanie :) /etc/init.d/bluetooth restart nie wystarczy.

(dodatkowe kroki próbowałem):

Przejrzałem swoją historię. Próbowałem również następujących, w których jeden lub drugi mógł przyczynić się do powyższego rozwiązania:

  • apt-get install pulseaudio-module-bluetooth (w moim systemie nie został zainstalowany)
  • logi wspomniały coś o brakowaniu ofono, więc również to zainstalowałem
  • zrobił sudo chown -R $USER ~/*
  • zastosował także: /ubuntu//a/691299/558838 (Jednak cofnąłem go, ponieważ to nie pomogło. Ale mogło nadal być aktywne, gdy próbowałem automatycznego połączenia)
  • czyściłem też / instalowałem pulseaudio, blueman, bluetooth packag
Roland
źródło
Dziękujemy za próbę pomocy, po prostu przetestowałem to, awaria, gdy tylko spróbowałem. Potem spróbowałem: moduł modułu pactl load-bluetooth-Discover i ponownie wcisnąłem zasilanie, ponownie rozbił pulseaudio: /
Joakim Koed
Dodano dodatkowe kroki do odpowiedzi, które próbowałem. Jeśli potrzebujesz szczegółowych informacji, po prostu zapytaj.
Roland,
DOBRZE. Dzisiaj dowiedziałem się czegoś innego: po śnie nie mogłem znów uruchomić. Nadal działa po ponownym uruchomieniu. Co gorsza: jak tylko połączenie Bluetooth zostanie nawiązane, moje połączenie bezprzewodowe już nie działa. Pozostaje podłączony, ale niczego nie przesyła. Muszę to jeszcze zbadać.
Roland,
Zapraszam do oznaczenia siebie jako dotkniętych: bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1574324
Joakim
Naprawiłem wifi / bluetooth problemu współistnienia z następujących czynności: askubuntu.com/a/645072/558838 :) Czy znowu sen i dostał z powrotem połączenie Bluetooth ... więc może będę musiał sprawdzić, co jeszcze zrobiłem tak, że teraz działa ... Może błąd koegzystencji był również problemem dla stabilnego połączenia? Przynajmniej brzmi to rozsądniej niż inne rzeczy, które wymieniłem :-) Czy mógłbyś też tego spróbować?
Roland,
1

Uruchom skrypt tutaj na GitHub

Problem zniknie.

#! /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
źródło