Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fixing bluetooth stereo headphone/headset problem in ubuntu 16.04, 16.10 and also debian jessie, with bluez5.
#! /usr/bin/env python3
"""Fixing bluetooth stereo headphone/headset problem in debian distros.
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
Install with:
curl "https://gist.githubusercontent.com/pylover/d68be364adac5f946887b85e6ed6e7ae/raw/install.sh" | sh
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
See ``a2dp.py -h`` for help.
Check here for 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
* https://github.com/Mihara, for autodetect & autorun service
* https://github.com/dabrovnijk, for systemd service
Change Log
----------
- 0.6.2
* Fix program name inside the help message.
- 0.6.1
* Fix Py warning
- 0.6.0
* Install script
- 0.5.2
* Increasing the number of tries to 15.
- 0.5.2
* Optimizing waits.
- 0.5.1
* Increasing WAIT_TIME and TRIES
- 0.5.0
* Autodetect & autorun service
- 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.6.2'
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 = 2.25
TRIES = 15
PROFILE = 'a2dp'
_profiles = {
'a2dp': 'a2dp_sink',
'hsp': 'headset_head_unit',
'off': 'off'
}
# CLI Arguments
parser = argparse.ArgumentParser()
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(delay=None):
return await asyncio.sleep(WAIT_TIME or delay)
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 == '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 wait(2)
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())))
#!/usr/bin/python
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import subprocess
import time
# Where you keep the above script. Must be executable, obviously.
A2DP = '/home/mihara/.local/bin/a2dp'
# A list of device IDs that you wish to run it on.
DEV_IDS = ['00:18:09:30:FC:D8','FC:58:FA:B1:2D:25']
device_paths = []
devices = []
dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)
def generate_handler(device_id):
last_ran = [0] # WHOA, this is crazy closure behavior: A simple variable does NOT work.
def cb(*args, **kwargs):
if args[0] == 'org.bluez.MediaControl1':
if args[1].get('Connected'):
print("Connected {}".format(device_id))
if last_ran[0] < time.time() - 120:
print("Fixing...")
subprocess.call([A2DP,device_id])
last_ran[0] = time.time()
else:
print("Disconnected {}".format(device_id))
return cb
# Figure out the path to the headset
man = bus.get_object('org.bluez', '/')
iface = dbus.Interface(man, 'org.freedesktop.DBus.ObjectManager')
for device in iface.GetManagedObjects().keys():
for id in DEV_IDS:
if device.endswith(id.replace(':','_')):
device_paths.append((id, device))
for id, device in device_paths:
headset = bus.get_object('org.bluez', device)
headset.connect_to_signal("PropertiesChanged", generate_handler(id), dbus_interface='org.freedesktop.DBus.Properties')
devices.append(headset)
loop = gobject.MainLoop()
loop.run()
[Unit]
Description=Fix BT Speaker
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/fix-bt.py
[Install]
WantedBy=multi-user.target
#! /usr/bin/env bash
URL="https://gist.githubusercontent.com/pylover/d68be364adac5f946887b85e6ed6e7ae/raw/a2dp.py"
TARGET=/usr/local/bin/a2dp.py
curl $URL | sudo tee ${TARGET} > /dev/null
sudo chmod +x $TARGET
echo "a2dp installation was successfull."
echo "Run a2dp.py [-h/--help] and enjoy the HiFi music!"
@sherlockhomeless
Copy link

sherlockhomeless commented Nov 1, 2018

Works for Ubuntu 18.10 too. Well done!

@benabdullah
Copy link

benabdullah commented Dec 28, 2018

you are great man !!!
thank you very much. @pylover

@mpaluchowski
Copy link

mpaluchowski commented Feb 22, 2019

This just fixed my sound problem in Ubuntu 18.10, so the issue lives on. Thanks @pylover!

@aaronliruns
Copy link

aaronliruns commented Feb 22, 2019

Fixed my bluetooth headphone issue with ubuntu 18.10 just now. Bravo!

@R13e
Copy link

R13e commented Mar 22, 2019

Works like a charm. Thanks @pylover!

@neteler
Copy link

neteler commented Apr 16, 2019

Great, the script fixed the error "Device sucessfully added but failed to connect" of my Bose Soundlink on Fedora 29 - thanks!

@JD3347
Copy link

JD3347 commented Apr 19, 2019

Worked for me on Ubuntu 18.04 kde (kubuntu). This is a solid script, thanks!

@fmunirdev
Copy link

fmunirdev commented May 1, 2019

Worked for me on Fedora 30 ... Perfect script, thank you!

@chrycon
Copy link

chrycon commented Jun 22, 2019

Linux Mint 18.3 worked PERFECTLY. what????

@DonKeyHot1
Copy link

DonKeyHot1 commented Jun 27, 2019

Worked on ubuntu 18.04
Thanks!

@juliolopeztorres
Copy link

juliolopeztorres commented Jul 9, 2019

Working perfectly on Kubuntu 19.04. Thank you!

@tobiasweede
Copy link

tobiasweede commented Jul 11, 2019

Linux Mint 18.3
Sony WH1000-MX3

Took me nearly a whole day to get a sound out of this little beast :) ...

Thanks!

Two comments:

1.) If python3 is used as system default, the fix-bt.py needs a little modification for the gobject import:
from gi.repository import GObject as gobject

2.) If pulseaudio is run in user mode, the systemd service - of course - needs to be run as the corresponding user:

[Service]
# ...
User=foo
Group=foo

@pylover
Copy link
Author

pylover commented Jul 12, 2019

@tobiasweede, Thanks in advance.

@sayalideo
Copy link

sayalideo commented Jul 27, 2019

Thanks a lot! This worked like a charm.

@mythly
Copy link

mythly commented Sep 12, 2019

u saved my day. Thanks!

@bryanhughes
Copy link

bryanhughes commented Oct 31, 2019

Thanks for the script. Unfortunately I am getting the following failure:

Connection MADE
Selecting device:
1. A0:E9:DB:5D:AC:57 Marley Liberate BT
2. 48:C1:AC:5D:45:8A PLT_Legend
Select device[1]:
1
Device MAC: A0:E9:DB:5D:AC:57
Device ID: bluez_card.A0_E9_DB_5D_AC_57
Sink: bluez_sink.A0_E9_DB_5D_AC_57
Updating default sink to bluez_sink.A0_E9_DB_5D_AC_57
Setting the off profile
Disconnecting the device.
Connecting again.
Cannot find `bluez_card.A0_E9_DB_5D_AC_57` using `pactl list cards short`. Retrying 15 more times
Device ID: bluez_card.A0_E9_DB_5D_AC_57
Setting the a2dp profile
Command: pactl set-card-profile bluez_card.A0_E9_DB_5D_AC_57 a2dp_sink failed with status: 1
stderr: Failure: Input/Output error

I am trying to get bluetooth audio to work on a Beagle Bone Green that is Debian 9.9. I am using a Broadcom Corp. BCM20702A0 Bluetooth 4.0 USB dongle. I am fairly new to working with bluetooth audio on linux. Any suggestions or help would be greatly appreciated. In the meantime will continue to research the failure.

Thanks!

@mitriy
Copy link

mitriy commented Nov 1, 2019

@pylover @Mihara I suppose we can auto-detect device mac addresses so the script is more flexible and user-friendly.
Not sure if this is reliable enough, but it's working for me. Please, review and feel free to add to fix-bt.py around line 38

# Attempt to auto-detect previously paired bluetooth devices
if not len(DEV_IDS):
    manager_obj = iface.GetManagedObjects()
    for path, ifaces in manager_obj.items():
        device_path = next((key for key in ifaces.keys()
                            if key.startswith('org.bluez.Device')), None)
        if not device_path:
            continue
        device = ifaces.get(device_path)

        if (
            bool(device.get('Paired'))
            and str(device.get('Icon', '')).startswith('audio')
            and device.get('Address')
        ):
            DEV_IDS.append(str(device['Address']))

    print('Paired bluetooth audio devices: {}'.format(DEV_IDS))

@lmoschcau
Copy link

lmoschcau commented Nov 4, 2019

Thanks. It stereo works now for me

@matipan
Copy link

matipan commented Nov 6, 2019

Worked like a charm on ubuntu 19.10! Thanks! 👍

@aarunishsinha
Copy link

aarunishsinha commented Jan 11, 2020

Dude!!! this thing worked like a charm on my Ubuntu 18.04....had been trying to listen to audio using my headphones for a week but had no success until this. Thank You! :)

@cjcheema
Copy link

cjcheema commented Apr 5, 2020

Thanks @pylover your python script is working fine on my Ubuntu 18.04 LTS Laptop I was facing problem with my Mivi Roam Bluetooth speaker. It seems Ubuntu update for 18.04 LTS has bug as I am start getting problem after applying updates.
I have done small tweak in your script shebang, in your python script shebang has this line: #! /usr/bin/env python3.5 whereas I am using python 3.6 and same is mentioned in my shell envoirnment so I have changed the shebang line in your script to #! /usr/bin/env python3.6 which worked fine for me and fixed the Bluetooth issue in my system. Thanks once again :)

@HaralDev
Copy link

HaralDev commented Apr 28, 2020

Worked well with Elementary OS.
LSB Version: core-9.20170808ubuntu1-noarch:printing-9.20170808ubuntu1-noarch:security-9.20170808ubuntu1-noarch Distributor ID: elementary Description: elementary OS 5.1.3 Hera

@bitfasching
Copy link

bitfasching commented Oct 20, 2020

A useful workaround for the missing audio profile bug in blueman after upgrading to Ubuntu 20.04. Thank you so much 🙏

@smiley2016
Copy link

smiley2016 commented Nov 13, 2020

Ah thanks. it's useful and works like a charm. OS Ubuntu 20.04.1 LTS 64 bit

@samds49
Copy link

samds49 commented May 18, 2021

I have the same problem than @bryanhughes when i ran the script :
`python3.8 a2dp.py
a2dp.py:363: SyntaxWarning: "is" with a literal. Did you mean "=="?
if args.profile is 'a2dp':
Connection MADE
Selecting device:

  1. 81:8E:35:BC:B5:00 ELEGIANT SR300
  2. 30:50:75:52:2B:B0 Jabra Evolve 65
  3. 00:23:13:01:F0:CA iTeknic IK-BH004
    Select device[1]:
    3
    Device MAC: 00:23:13:01:F0:CA
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 15 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 14 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 13 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 12 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 11 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 10 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 9 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 8 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 7 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 6 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 5 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 4 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 3 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 2 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 1 more times
    Device ID: bluez_card.00_23_13_01_F0_CA
    Sink: bluez_sink.00_23_13_01_F0_CA
    Updating default sink to bluez_sink.00_23_13_01_F0_CA
    Setting the off profile
    Disconnecting the device.
    Connecting again.
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 15 more times
    Cannot find bluez_card.00_23_13_01_F0_CA using pactl list cards short. Retrying 14 more times
    Device ID: bluez_card.00_23_13_01_F0_CA
    Setting the a2dp profile
    Command: pactl set-card-profile bluez_card.00_23_13_01_F0_CA a2dp_sink failed with status: 1
    stderr: Échec : Erreur d'entrée/sortie
    Can you help me please ?
    `

@Schwuuuuup
Copy link

Schwuuuuup commented May 28, 2021

@samds49 mine is very simmilar:

╰─➤  python3 ./a2dp.py
./a2dp.py:365: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if args.profile is 'a2dp':
Connection MADE
Selecting device:
Device MAC: 00:5A:5A:A6:00:CF
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 15 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 14 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 13 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 12 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 11 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 10 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 9 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 8 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 7 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 6 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 5 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 4 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 3 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 2 more times
Cannot find `bluez_card.00_5A_5A_A6_00_CF` using `pactl list cards short`. Retrying 1 more times
It seems device: 00:5A:5A:A6:00:CF is not connected yet, trying to connect.
Connecting again.
Expression "Failed to connect: org.bluez.Error.Failed" failed with fail pattern: "fail"
Exiting bluetoothctl

This is on a freshly installed Linux Mint 20.1

@Schwuuuuup
Copy link

Schwuuuuup commented May 28, 2021

Hmm on my machine a2dp was not available (in the pulse audio volume tool it was listed, but listed as "not available"

I found a post that helped me:

sudo dpkg-reconfigure bluez
sudo dpkg-reconfigure linux-sound-base

@pylover
Copy link
Author

pylover commented Jun 23, 2021

The Installation script is ready for those who can't copy and set the executable flag of a file in Linux. So just do:

curl "https://gist.githubusercontent.com/pylover/d68be364adac5f946887b85e6ed6e7ae/raw/install.sh" | sh

@arsinclair
Copy link

arsinclair commented Jul 29, 2021

The issue with my Jabra Elite 75t was something like:

Cannot find bluez_card.00_5A_5A_A6_00_CF using pactl list cards short. Retrying 6 more times

The headset would be connected in Bluetooth manager successfully, but the audio interface wouldn't appear. Turns out, the only supported by the device protocol is not immediately available in my debian 10 KDE. However, based on this reddit thread https://www.reddit.com/r/Jabra/comments/j5489d/if_you_use_jabra_earbuds_with_linux_you_need_to I've found that someone has made a package integrating this stuff - available in https://github.com/EHfive/pulseaudio-modules-bt. The package is deprecated as maintainer now switched to PipeWire (and it supports the codec), but I've built pulseaudio-modules-bt and installed it on my debian, and it still works perfectly.

Someone even made an installer here https://github.com/lagerimsi-ds/debian-buster_bluetooth_aptX-LDAC, but use it with caution.

@moorepants
Copy link

moorepants commented Nov 13, 2021

I'm getting this failure:

Ignoring: Command: pacmd list-sink-inputs | grep "index:" failed with status: 1
stderr:

Running that command gives:

$ pacmd list-sink-inputs
0 sink input(s) available.

The headset is connected, ubuntu settings show the headset selected with a2dp sink, but the sound continues to come out of my speakers that are connected by traditional audio cable to my sound card.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment