-
-
Save pylover/d68be364adac5f946887b85e6ed6e7ae to your computer and use it in GitHub Desktop.
#! /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!" | |
@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
I got the same issue linux mint 21.3 nothing has changed eh, the a2dp unfixes the fix when you use
sudo dpkg-reconfigure bluez
sudo dpkg-reconfigure linux-sound-base
For example, right now I have sound and it works. Then I do a2dpy, and the following happens.
kreijstal@kreijstalnuc:~$ pactl list sinks short
5 bluez_sink.E8_AB_FA_40_25_3B.a2dp_sink module-bluez5-device.c s16le 2ch 48000Hz SUSPENDED
kreijstal@kreijstalnuc:~$ a2dp.py
Connection MADE
Selecting device:
Device MAC: E8:AB:FA:40:25:3B
Device ID: bluez_card.E8_AB_FA_40_25_3B
Sink: bluez_sink.E8_AB_FA_40_25_3B
Updating default sink to bluez_sink.E8_AB_FA_40_25_3B
Setting the off profile
Disconnecting the device.
Connecting again.
Cannot find `bluez_card.E8_AB_FA_40_25_3B` using `pactl list cards short`. Retrying 15 more times
Cannot find `bluez_card.E8_AB_FA_40_25_3B` using `pactl list cards short`. Retrying 14 more times
Cannot find `bluez_card.E8_AB_FA_40_25_3B` using `pactl list cards short`. Retrying 13 more times
Cannot find `bluez_card.E8_AB_FA_40_25_3B` using `pactl list cards short`. Retrying 12 more times
So running the script unfixes the situation, do no harm, eh?
just something I am testing
kreijstal@kreijstalnuc:~$ pactl list sinks short
Verbindungsfehler: Verbindung verweigert
pa_context_new() fehlgeschlagen: Verbindung verweigert
kreijstal@kreijstalnuc:~$ pulseaudio -D
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz IDLE
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz IDLE
kreijstal@kreijstalnuc:~$ pkill pulseaudio
pkill: Abwürgen von Prozess-ID 5970 fehlgeschlagen: Vorgang nicht zulässig
kreijstal@kreijstalnuc:~$ pactl list sinks short
Verbindungsfehler: Verbindung verweigert
pa_context_new() fehlgeschlagen: Verbindung verweigert
kreijstal@kreijstalnuc:~$ sudo pulseaudio -D
[sudo] Passwort für kreijstal:
W: [pulseaudio] main.c: Dieses Programm sollte ohne die Option --system nicht als Administrator ausgeführt werden.
kreijstal@kreijstalnuc:~$ pactl list sinks short
Verbindungsfehler: Verbindung verweigert
pa_context_new() fehlgeschlagen: Verbindung verweigert
kreijstal@kreijstalnuc:~$ pulseaudio -D
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz IDLE
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz IDLE
kreijstal@kreijstalnuc:~$ sudo pulseaudio -D^C
kreijstal@kreijstalnuc:~$ sudo dpkg-reconfigure linux-sound-base
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ sudo dpkg-reconfigure bluez
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ pactl list sinks short
1 bluez_sink.E8_AB_FA_40_25_3B.handsfree_head_unit module-bluez5-device.c s16le 1ch 16000Hz IDLE
kreijstal@kreijstalnuc:~$ pactl list sinks short
1 bluez_sink.E8_AB_FA_40_25_3B.handsfree_head_unit module-bluez5-device.c s16le 1ch 16000Hz IDLE
kreijstal@kreijstalnuc:~$ pactl list sinks short
1 bluez_sink.E8_AB_FA_40_25_3B.handsfree_head_unit module-bluez5-device.c s16le 1ch 16000Hz IDLE
kreijstal@kreijstalnuc:~$ echo we have now audio
we have now audio
kreijstal@kreijstalnuc:~$ pulseaudio -k
kreijstal@kreijstalnuc:~$ pulseaudio -D
kreijstal@kreijstalnuc:~$ pactl list sinks short
0 auto_null module-null-sink.c s16le 2ch 44100Hz IDLE
kreijstal@kreijstalnuc:~$ echo we have no audio
we have no audio
sledge hammer solution, experts please help
kreijstal@kreijstalnuc:~$ pactl list sources short
13 bluez_sink.E8_AB_FA_40_25_3B.handsfree_head_unit.monitor module-bluez5-device.c s16le 1ch 16000Hz SUSPENDED
14 bluez_source.E8_AB_FA_40_25_3B.handsfree_head_unit module-bluez5-device.c s16le 1ch 16000Hz SUSPENDED
kreijstal@kreijstalnuc:~$ bluetoothctl
Agent registered
[TaoTronics SoundSurge 90]# disconnect E8:AB:FA:40:25:3B
Attempting to disconnect from E8:AB:FA:40:25:3B
Successful disconnected
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B Connected: no
[bluetooth]# isconnect E8:AB:FA:40:25:3B
[bluetooth]# exit
kreijstal@kreijstalnuc:~$ rm -rf /var/lib/blue
blueman/ bluetooth/
kreijstal@kreijstalnuc:~$ rm -rf /var/lib/blue
blueman/ bluetooth/
kreijstal@kreijstalnuc:~$ sudo rm -rf /var/lib/bluetooth/
kreijstal@kreijstalnuc:~$ pacmd set-card-profile 1 handsfree_head_unit^C
kreijstal@kreijstalnuc:~$ sudo dpkg-reconfigure bluez
Job for bluetooth.service failed because the control process exited with error code.
See "systemctl status bluetooth.service" and "journalctl -xeu bluetooth.service" for details.
invoke-rc.d: initscript bluetooth, action "restart" failed.
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Fri 2024-02-09 16:13:46 CET; 25ms ago
Docs: man:bluetoothd(8)
Process: 51980 ExecStart=/usr/lib/bluetooth/bluetoothd (code=exited, status=226/NAMESPACE)
Main PID: 51980 (code=exited, status=226/NAMESPACE)
CPU: 4ms
kreijstal@kreijstalnuc:~$ sudo mkdir /var/lib/bluetooth/
kreijstal@kreijstalnuc:~$ ls
Bilder CytoscapeConfiguration Downloads go micromamba OldRunescapeSoundtrack_vbr.m3u Schreibtisch thinclient_drives Videos
bin Dokumente git LICENSE Musik Passwörter.kdbx tar Untitled.ipynb Vorlagen
kreijstal@kreijstalnuc:~$ bluetoothctl
Waiting to connect to bluetoothd...
kreijstal@kreijstalnuc:~$ sudo service bluetooth restart
kreijstal@kreijstalnuc:~$ bluetoothctl
Agent registered
[bluetooth]# scan
☺☻Missing on/off/bredr/le argument☺☻
[bluetooth]# scan on
Discovery started
[☺☻CHG☺☻] Controller B0:DC:EF:9E:2B:35 Discovering: yes
[☺☻NEW☺☻] Device 48:74:12:56:42:1A OnePlus 10 Pro 5G
[☺☻NEW☺☻] Device 2F:E0:1C:4C:5E:C0 2F-E0-1C-4C-5E-C0
[☺☻NEW☺☻] Device 00:1A:7D:DA:71:15 LPT-FFO-00-0134
[☺☻NEW☺☻] Device E8:AB:FA:40:25:3B TaoTronics SoundSurge 90
[☺☻NEW☺☻] Device D4:D7:CF:2C:B3:B2 D4-D7-CF-2C-B3-B2
[☺☻CHG☺☻] Device 2F:E0:1C:4C:5E:C0 Name: DQ-M2
[☺☻CHG☺☻] Device 2F:E0:1C:4C:5E:C0 Alias: DQ-M2
[☺☻CHG☺☻] Device 2F:E0:1C:4C:5E:C0 ManufacturerData Key: 0x5754
[☺☻CHG☺☻] Device 2F:E0:1C:4C:5E:C0 ManufacturerData Value:
53 4d 4f aa 58 SMO.X
[bluetooth]# pair E8:AB:FA:40:25:3B
Attempting to pair with E8:AB:FA:40:25:3B
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B Connected: yes
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B ServicesResolved: yes
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B Paired: yes
Pairing successful
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B ServicesResolved: no
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B Connected: no
[bluetooth]# connect E8:AB:FA:40:25:3B
Attempting to connect to E8:AB:FA:40:25:3B
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B Connected: yes
Connection successful
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B ServicesResolved: yes
[TaoTronics SoundSurge 90]# trust E8:AB:FA:40:25:3B
[☺☻CHG☺☻] Device E8:AB:FA:40:25:3B Trusted: yes
Changing E8:AB:FA:40:25:3B trust succeeded
[TaoTronics SoundSurge 90]# exit
kreijstal@kreijstalnuc:~$ pactl list sinks short
11 bluez_sink.E8_AB_FA_40_25_3B.a2dp_sink module-bluez5-device.c s16le 2ch 44100Hz SUSPENDED
kreijstal@kreijstalnuc:~$ it works now, wow, was that hard?
I have to do this party trick almost every day lol
kreijstal@kreijstalnuc:~$ a2dp.py
Connection MADE
Selecting device:
Device MAC: E8:AB:FA:40:25:3B
Device ID: bluez_card.E8_AB_FA_40_25_3B
Sink: bluez_sink.E8_AB_FA_40_25_3B
Updating default sink to bluez_sink.E8_AB_FA_40_25_3B
Setting the off profile
Disconnecting the device.
Connecting again.
Device ID: bluez_card.E8_AB_FA_40_25_3B
Setting the a2dp profile
Updating default sink to bluez_sink.E8_AB_FA_40_25_3B
Moving stream 1 to sink
Moving stream 2 to sink
Exiting bluetoothctl
"Enjoy" the HiFi stereo music :)
kreijstal@kreijstalnuc:~$
Ok, but we know it can also do microphone just like before, let us try it.
kreijstal@kreijstalnuc:~$ a2dp.py -p hsp
Connection MADE
Selecting device:
Device MAC: E8:AB:FA:40:25:3B
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 15 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 14 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 13 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 12 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 11 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 10 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 9 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 8 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 7 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 6 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 5 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 4 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 3 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 2 more times
Cannot find `bluez_sink.E8_AB_FA_40_25_3B` using `pacmd list-sinks`. Retrying 1 more times
Setting the hsp profile
Command: pactl set-card-profile bluez_card.E8_AB_FA_40_25_3B headset_head_unit failed with status: 1
stderr: Fehlgeschlagen: Entität nicht vorhanden
Exiting bluetoothctl
huh, so now I can not do audio calls? but before I could :(
i just need to start pipewire service locally, not glboally, so no pulseaudio, right, systemctl --user status pipewire
should fix pactl lists not being available, right?
so everytime I restarted pactl list was unavailable because pipewire pulseaudio was masked,
sudo apt update
sudo apt install --reinstall pipewire pipewire-pulse pipewire-audio-client-libraries
after this noo other tricks ever worked and audio never worked again and I gave up, I could uninstall and reinstall pulseaudio but I cant bother.
I kinda solved it, these were the steps...
upgraded to latest version pipewire ppa
remove blueman
edit /etc/bluetooth/audio.conf
~$ cat /etc/bluetooth/audio.conf
[General]
Enable=Control,Gateway,Headset,Media,Sink,Socket,Source
mv .config/systemd to .config/systemd.backup
uninstall https://old.reddit.com/r/pop_os/comments/ol9nxx/installing_latest_pipewire_with_working_bluetooth/
install wireplumber
sudo rm /etc/systemd/user/pipewire-media-session.service
systemctl --user --now enable wireplumber.service
systemctl --user start wireplumber.service
sudo rm -rf /var/lib/bluetooth/*
DEVICE_MAC=$(bluetoothctl devices | awk '/Device/{print $2}')
# Step 5: Pair, trust, and connect to the Bluetooth device
echo "Pairing, trusting, and connecting to the Bluetooth device..."
echo -e "pair $DEVICE_MAC\ntrust $DEVICE_MAC\nconnect $DEVICE_MAC\nquit" | bluetoothctl
New problems: Now it is either a2p or hfp , cant switch, but now I get 3 different profiles..
Profile:
off: Off (Ziele: 0, Quellen: 0, Priorität: 0, verfügbar: ja)
a2dp-sink-sbc: High Fidelity Playback (A2DP Sink, codec SBC) (Ziele: 1, Quellen: 0, Priorität: 18, verfügbar: ja)
a2dp-sink-sbc_xq: High Fidelity Playback (A2DP Sink, codec SBC-XQ) (Ziele: 1, Quellen: 0, Priorität: 17, verfügbar: ja)
a2dp-sink: High Fidelity Playback (A2DP Sink, codec AAC) (Ziele: 1, Quellen: 0, Priorität: 19, verfügbar: ja)
Aktives Profil: a2dp-sink
```
remove bluetooth reconenct and pray you get the hfp profile
Settings
└─ Default Configured Node Names:
0. Audio/Sink bluez_output.E8_AB_FA_40_25_3B.headset-head-unit
kreijstal@kreijstalnuc:~$ pactl list sinks short
165 bluez_output.E8_AB_FA_40_25_3B.headset-head-unit PipeWire s16le 1ch 16000Hz RUNNING
It's either stuck on headset-head-unit or a2dp-sink, only with wireplumber, things worked before, but oh well. omg
so I rebooted and sound was gone again, and I perfomed my daily ritual of trying random commands to see what sticks to the wall, I dont like casting
sudo dpkg-reconfigure bluez
sudo dpkg-reconfigure linux-sound-base
but it seems in this case that did the trick along with other things.. let's see if it survives this reboot,
everything was fixed with Mint 22. Finally.
@aniruddha564 All the installation does is to create the file
/usr/local/bin/a2dp.py
. This file will do nothing unless you explicitly call it somehow, e.g. from a terminal:Or from some other launcher like a custom keyboard shortcut.
If you wish to uninstall it, you could do so from the terminal with: