Skip to content

Instantly share code, notes, and snippets.

@pylover pylover/a2dp.py
Last active Sep 15, 2019

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.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
* https://github.com/Mihara, for autodetect & autorun service
* https://github.com/dabrovnijk, for systemd service
Change Log
----------
- 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.5.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(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(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 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 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
@ragusa87

This comment has been minimized.

Copy link

commented Sep 12, 2016

Thanks @pylover, you made my day!

@DeathCamel57

This comment has been minimized.

Copy link

commented Sep 16, 2016

Thank you so, so much!

@herrfz

This comment has been minimized.

Copy link

commented Sep 25, 2016

Without the main function this could actually be an async/await-based library for interacting with bluetoothctl ... brilliant!

@tavurth

This comment has been minimized.

Copy link

commented Sep 29, 2016

Great script, fixed my issue for bluetooth headphones MDR-ZX770BT. Thanks @pylover!

@theweirdguy

This comment has been minimized.

Copy link

commented Oct 1, 2016

Man u are a savior, thanks bro #<3 python

@dginev

This comment has been minimized.

Copy link

commented Oct 4, 2016

Thanks @pylover this gist is a major convenience boost for me. Do you have any advice who/where to ping to resolve the mainline issue?

@RobRobM

This comment has been minimized.

Copy link

commented Oct 21, 2016

sorry, still not working:

./bin/a2dp.py 
Connection MADE
Selecting device:
There is no connected device.
Exiting bluetoothctl
bluetoothctl 
[NEW] Controller 5C:F3:70:68:D9:1B desktop [default]
[NEW] Device FC:F1:52:1E:DB:99 MDR-ZX750BN
[bluetooth]# 
@pylover

This comment has been minimized.

Copy link
Owner Author

commented Oct 21, 2016

@RobbieFM: Please pair and connect your headset before running this script.

@RobRobM

This comment has been minimized.

Copy link

commented Oct 22, 2016

The Sony headset MDR-ZX750BN was paired and connected. I can switch to a2dp by first settings the profile to HSP/Hfp profile, then disconnect and reconnect via blueman, then I can switch to a2dp. I was hoping your script would automate this.

If you need me to test anything, just let me know.

I have a Sony headset MDR-ZX750BN and Sony speaker Srs-x33 to test with.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Oct 22, 2016

@RobbieFM, Interesting, thanks a lot for feedback.

I have no ubuntu 16.10 installed, so wait to i download, install & test it.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Oct 23, 2016

@RobbieFM, it's fixed on 0.2.3.

Thanks a lot for reporting.

@RobRobM

This comment has been minimized.

Copy link

commented Oct 24, 2016

@pylover, sorry still not working. I do get new errors:

Connection MADE
Selecting device:
Device MAC: FC:F1:52:1E:DB:99
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 8 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 7 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 6 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 5 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 4 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 3 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 2 more times
Cannot find bluez_sink.FC_F1_52_1E_DB_99 using pacmd list-sinks. Retrying 1 more times
Command: pactl set-card-profile bluez_card.FC_F1_52_1E_DB_99 a2dp_sink failed with status: 1
stderr: Mislukt: Invoer-/Uitvoerfout (I/O)

Exiting bluetoothctl

Ps. thanks for your very quick responses

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Oct 24, 2016

It's may be something else, here is working well on ubuntu 16.10.

So, ensure the headset is shown on sound control. increasing wait time -w and tries -t. may help.

Run pacmd list-sinks manually to ensure the sink is created.

@romanovzky

This comment has been minimized.

Copy link

commented Nov 8, 2016

You can't imagine how much I appreciate this! Thanks a lot mate, big help!

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Nov 8, 2016

@romanovzky, Thanks for comment.

@MoonDogg

This comment has been minimized.

Copy link

commented Nov 9, 2016

I can confirm this working on GalliumOS 2.0 (Xubuntu 16.04) on a Acer C720. Thanks!! My only issue is that I have if I disconnect my headset and reconnect I have to delete it and re-pair and rerun script for it to work again. Any suggestions?

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Nov 9, 2016

@MoonDogg, This script is written to prevent manualy turning off, and connection again. so if it's not working, as well as i told you. there are some problems.

@MoonDogg

This comment has been minimized.

Copy link

commented Nov 9, 2016

I think it was a miss communication... it works... I meant after I turn my device off and then go to reconnect it later... it connects but not working in A2PD if I re-run the script it works fine. Is there a way to make the script run automatically every time I connect a A2DP device?

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Nov 10, 2016

@MoonDogg, Good idea, but how ?

@MoonDogg

This comment has been minimized.

Copy link

commented Nov 10, 2016

@pylover, I was hoping you would know. :P I am going to do some research see if I can figure it out. I will let you know what I find.

@MoonDogg

This comment has been minimized.

Copy link

commented Nov 10, 2016

@pylover, I found this.. http://askubuntu.com/questions/138522/how-do-i-run-a-script-when-a-bluetooth-device-connects and it uses this script ( https://github.com/yxlao/bluetooth-runner ) when a blue-tooth device connects.. I just don't know the syntax to edit it to call your script. Maybe you could modify it?

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Nov 10, 2016

@MoonDogg, Thanks a lot

@agorelick

This comment has been minimized.

Copy link

commented Nov 12, 2016

Thank you! This is great, works flawlessly :)

@MoonDogg

This comment has been minimized.

Copy link

commented Nov 14, 2016

@pylover are you editing the script I linked to call your script or are you incorporating it into your script? Either way let me know and I can test it out for you. Thanks for you help.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Nov 14, 2016

@MoonDogg, i'll do it in the next a few days . thanks a lot for contribution

@acidreign

This comment has been minimized.

Copy link

commented Nov 18, 2016

This script saves me from a giant headache I was suffering through on a daily basis. You are THE MAN @pylover!!

@edelreal

This comment has been minimized.

Copy link

commented Nov 25, 2016

Wonderful workaround, thanks!

I've posted details of my debugging attempts to https://bugs.freedesktop.org/show_bug.cgi?id=92102 ;
perhaps it is something pulseaudio can learn to handle (unless this is a bug that needs to fixed in bluez instead).

@bobberkarl

This comment has been minimized.

Copy link

commented Dec 1, 2016

3 years of Connecting/deconnecting were just solved. Thank you @pylover .

@ghost

This comment has been minimized.

Copy link

commented Dec 6, 2016

Kind thanks for this script kind sirs! You have saved my from six month struggle with bluetooth on my laptop!

@VirToReal

This comment has been minimized.

Copy link

commented Dec 8, 2016

Thanks Sir Awesome!

@peteruithoven

This comment has been minimized.

Copy link

commented Dec 8, 2016

One great addition would be using pactl subsribe to automatically perform this when a device is connected.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Dec 8, 2016

@peteruithoven thanks a lot

@frankitox

This comment has been minimized.

Copy link

commented Dec 18, 2016

Maaaan! Thanks!!! I wasted my whole afternoon with this shit. God. Just a chmod u+x a2dp.py && mv a2dp.py ~/.bin/speakers and everything's good to go. Working on Lubuntu 16.04.1.

@ytian801

This comment has been minimized.

Copy link

commented Dec 19, 2016

Works great in ubuntu 16.04.1, thank you so much

@ericek111

This comment has been minimized.

Copy link

commented Dec 19, 2016

Thanks, worked perfectly!

@opennomad

This comment has been minimized.

Copy link

commented Dec 19, 2016

Awesome. Works like a charm. Thank you!

@rigtersys

This comment has been minimized.

Copy link

commented Jan 6, 2017

Thanks a lot! Confirmed working on Linux Mint Sarah (is also ubuntu 16.04.1but you never know)

@oofnikj

This comment has been minimized.

Copy link

commented Jan 9, 2017

Hi,
Very cool script, thanks 👍
I had a problem where my device connected automatically with 'off' profile, which meant that it did not appear in pacmd list-sinks.
So I modified the code a little bit to connect in HSP/HFP mode and then look for the sink again.
Now it works flawlessly. I launch the script with a keyboard shortcut when I turn on my speakers.
Running Xubuntu 16.04.
Cheers

@wayne003

This comment has been minimized.

Copy link

commented Jan 9, 2017

Life saver!

@yamatban

This comment has been minimized.

Copy link

commented Jan 14, 2017

has anyone gotten the mic in the bluetooth headphones to work the system sees it but gets no input

@mlabisi

This comment has been minimized.

Copy link

commented Jan 17, 2017

Thank you so much!

@vmavromatis

This comment has been minimized.

Copy link

commented Jan 18, 2017

Works like a charm @ Lubuntu 16.10. Thanks!
I tried @moondog's suggestion for bluetooth-runner but unfortunately that script does not detect my bluetooth connection....

@doktrj289

This comment has been minimized.

Copy link

commented Jan 20, 2017

Worked perfectly first time but since reboot I keep getting the following error:
Command: pactl set-card-profile bluez_card.00_18_09_9B_EA_2F a2dp_sink failed with status: 1 stderr: Failure: Input/Output error
I tried setting a wait time to no avail, any other suggestions?

@peteruithoven

This comment has been minimized.

Copy link

commented Jan 21, 2017

I have a Bose Quietcontrol 30, switched laptops (now on a XPS15) (both ran Elementary Loki, based on Ubuntu 16.04), and it all worked fine for a while but after some updates the device stopped showing up as sound output. So I tried this script (thanks for sharing!) and just like @RobbieFM now I'm getting the following error:

Cannot find `bluez_card.04_52_C7_1B_7B_BC` using `pactl list cards short`. Retrying 8 more times

The device isn't showing up in the sound output's list, but that was the problem that I hoped to fix with this script. I don't see the device in the pacmd list-sinks list.

I tried the following suggestion: http://askubuntu.com/a/865214/519324

I tried pactl list short | grep bluetooth, but I'm not sure whether it's result is a good sign.

$ pactl list short | grep bluetooth
7	module-bluetooth-policy		
22	module-bluetooth-discover

I'll try to do some more research, but tips are welcome.

I found http://askubuntu.com/a/836202/519324 but Audio Profile didn't have a submenu. So I tried a couple of things, like pressing the Setup button and selecting Connect to: Handsfree. Suddenly it did appear in the Sounds output menu and the Audio Profile menu has options.
I also noticed that earlier my laptop appeared without a name in the bluetooth connects and now the proper name is shown.
Looks solved... No clue why or what went wrong.

@peteruithoven

This comment has been minimized.

Copy link

commented Jan 22, 2017

I can't edit my previous comment anymore, so I'll continue in a new one.
Using blueman to connect to my bluetooth device as handsfree doesn't seem to be a permanent fix, I have to do it after every reboot. I did notice that when I reboot my bluetooth device I get the following notification:

Bluetooth Authentication
Authorization request for: Bose QuietControl 30 (04:52:C7:1B:7B:BC)
Service: Advanced Audio

And a reboot later it works great, I only need to reboot the bluetooth device.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jan 22, 2017

@peteruithoven, yes you have to reboot your headset also

@Mihara

This comment has been minimized.

Copy link

commented Jan 26, 2017

In case it might be helpful to someone, here's how I invoke a2dp.py automatically in Ubuntu 16.04, only for specific headsets:

#!/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()

Usage: Put the device IDs of your A2DP devices into DEV_IDS and the full path of your a2dp.py into the A2DP variable. Run from Startup Applications. Whenever you connect an audio device listed, a2dp.py will be automatically run shortly to sort it out. This will not work on earlier versions of Ubuntu, because it depends on the DBus API flavor introduced in Bluez 5.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jan 28, 2017

@Mihara, Thank's a lot.

@tombrereton

This comment has been minimized.

Copy link

commented Feb 11, 2017

@pylover holy shit, thank you for saving my sanity

@ZlatanStanojevic

This comment has been minimized.

Copy link

commented Feb 16, 2017

You guys are my personal heroes!

@feryardiant

This comment has been minimized.

Copy link

commented Feb 20, 2017

Hi @pylover

Thanks for the script, but unfortunately I got this.

Connection MADE
Selecting device:
1. 00:01:01:00:02:DF AWEI-A980BL
2. AC:C1:EE:0D:9B:EA Mimin-R4
Select device[1]:
1
Device MAC: 00:01:01:00:02:DF
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 8 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 7 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 6 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 5 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 4 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 3 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 2 more times
Cannot find `bluez_sink.00_01_01_00_02_DF` using `pacmd list-sinks`. Retrying 1 more times
Device ID: bluez_card.00_01_01_00_02_DF
Sink: bluez_sink.00_01_01_00_02_DF
Turning off audio profile.
Disconnecting the device.
Connecting again.
Expression "Failed to connect: org.bluez.Error.Failed" failed with fail pattern: "fail"
Exiting bluetoothctl

Any idea?

@AJMaxwell

This comment has been minimized.

Copy link

commented Feb 22, 2017

Update: I had to put my headphones into "pairing" mode before running the script. After that, the script ran successfully.

@jvalenciag

This comment has been minimized.

Copy link

commented Feb 25, 2017

Worked very well on ubuntu 16.10, thank's a lot!

@RajatArora08

This comment has been minimized.

Copy link

commented Mar 3, 2017

Perfect! Problem solved! Thanks a ton @pylover

@jtryan

This comment has been minimized.

Copy link

commented Mar 5, 2017

@pylover Fantastic work! Using it on 16.10. Now I can get off fedora. Thanks

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 5, 2017

@jtryan, Good for you, get rid of yum and a lot of old and crappy tools.

@IzzySoft

This comment has been minimized.

Copy link

commented Mar 6, 2017

@feryardiant Yes. I just had the same, easy to fix. First, the bunch of "cannot find" can be ignored. The trouble is the connect command being issued before the device is ready, it needs a little sleep.

@pylover easy fix:

from time import sleep
…
print('Connecting again.')
sleep(2)
await protocol.connect(mac)

Did the job for me. Comment: importing sleep from time, then right after the print('Connecting again.') line add a sleep for 2 secs. Shouldn't hurt too much for those not needing it – but helps a lot for those who do 😺

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 6, 2017

@IzzySoft, This an asyncio script, You should not use time.sleep, because it will block the all async tasks. So, it's good to use asyncio.sleep function instead. And making a CLI argument for sleep time is appreciated.

@DominicWatson

This comment has been minimized.

Copy link

commented Mar 7, 2017

This is so good, thank you! I made some additions in my own fork to be able to specify which profile to use. This way I can add a -p headset_head_unit argument and use all the same logic to switch to headset mode for calls. I realize there's probably a separate script that could do this without as much code, but figured it made sense to re-use all the good logic you had around setting the output device, etc.

https://gist.github.com/DominicWatson/b1ea0563df1dcdad858926edca3cee01

For me, I then bind two keyboard shortcuts to the two commands:

python3.5 /path/to/a2dp.py -p a2dp_sink
python3.5 /path/to/a2dp.py -p headset_head_unit

# I should probably rename the script to something else given that its now not exclusively about a2dp, but meh

Again, thanks for the script. Fracking awesome. License is a bit restrictive though.

p.s. do you have a git tip / amazon wishlist or somesuch? would love to repay you.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 8, 2017

@DominicWatson, I'm very appreciate you comment. But i'm living at a country which the banking operations with the world are embargoed.
So, please find a homeless around your area and make him/her happy,

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 9, 2017

@DominicWatson, I merged your fork, thank's a lot for contributing. The -p/--profile is very useful.

@IzzySoft

This comment has been minimized.

Copy link

commented Mar 12, 2017

@pylover

This an asyncio script, You should not use time.sleep, because it will block the all async tasks. So, it's good to use asyncio.sleep function instead. And making a CLI argument for sleep time is appreciated.

Sure! Mine was just a "quick hack". I use Python myself here and there, but am not that deep into it – especially not into asyncio, which I admittedly never used myself. Thanks for picking up my "dirty fix" and converting it into a "clean update" 😸

@DominicWatson Very useful addition! I was asking myself for that as well. Glad I now can simply use it!

@dabrovnijk

This comment has been minimized.

Copy link

commented Mar 12, 2017

Thanks alot for the script, pylover for the a2dp.py and Mihara for the autostart script.

I have made this fix-bt.service as below. It will run the first time if I disconnect and reconnect my bluetooth speaker and it will fix a2dp_sink properly but it will only run one time and then I will have to restart the service.

fix-bt.py contains the script that Mihara have addded above.

But I do not know if I have made something wrong in my .service or if I should change something in Miharas script (besides what is already told to change in the script).

Should I use Type=dbus? But I do not know what I should write at BusName=, or how I will find that out.

[Unit]
Description=Fix BT Speaker

[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/fix-bt.py

[Install]
WantedBy=multi-user.target
@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 12, 2017

@dabrovnijk, Interesting, the systemd service is great!

@dabrovnijk

This comment has been minimized.

Copy link

commented Mar 12, 2017

Apperantly it seems to work I just had to be patient. When I tested again after couple of minutes it did what it was supposed to do.

I am running this on a headless Ubuntu 16.10 with pulseaudio running as system. I had to replace pacmd with pactl in your original script as pacmd did not find the pulseaudio daemon.

I love this output, and I can't praise you enough. +1:

mar 12 23:48:58 kompakt fix-bt.py[1107]: Device ID: bluez_card.00_02_3C_5E_28_91
mar 12 23:48:58 kompakt fix-bt.py[1107]: Sink: bluez_sink.00_02_3C_5E_28_91
mar 12 23:48:58 kompakt fix-bt.py[1107]: Turning off audio profile.
mar 12 23:48:58 kompakt fix-bt.py[1107]: Disconnecting the device.
mar 12 23:48:58 kompakt fix-bt.py[1107]: Connecting again.
mar 12 23:48:58 kompakt fix-bt.py[1107]: Device ID: bluez_card.00_02_3C_5E_28_91
mar 12 23:48:58 kompakt fix-bt.py[1107]: Setting the a2dp profile
mar 12 23:48:58 kompakt fix-bt.py[1107]: Updating default sink
mar 12 23:48:58 kompakt fix-bt.py[1107]: Exiting bluetoothctl
mar 12 23:48:58 kompakt fix-bt.py[1107]: "Enjoy" the HiFi stereo music :)

l

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 13, 2017

@dabrovnijk, It's OK, replace and test it.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 18, 2017

@ktatts, You have to pair/connect you headphones before running this script.

@guyviner

This comment has been minimized.

Copy link

commented Mar 24, 2017

NOOB/NOVICE/EASY/HOW TO INSTALL INSTRUCTIONS:

  1. Click 'Download Zip' at the top right corner of this page
  2. Save to desktop, choose a short name for it, like 'bluetooth'
  3. Go to your desktop
  4. Right click the file you just downloaded
  5. Choose 'Extract Here'
    5b) Pair your bluetooth headset.
  6. Open your terminal
  7. Navigate to the file by typing cd ~/Desktop/bluetooth
  8. Type python3.5 a2dp.py
  9. Choose the headset from the list, if a list pops up
  10. Done! Enjoy.

Thanks so much to @pylover for this script.

**Update. My guide may or may not be correct, because the script hasn't worked for me. I still need to connect twice to get A2DP to work. Can someone review my guide to see what I could have done wrong?

@FrostyPatronus

This comment has been minimized.

Copy link

commented Mar 27, 2017

Thank you very much! Works perfectly for Ubuntu 16.04

@neylsongularte

This comment has been minimized.

Copy link

commented Apr 8, 2017

thanks! Work on Elementary OS 0.4

@hamedaakhlaghi

This comment has been minimized.

Copy link

commented Apr 9, 2017

Thanks. It's worked perfect, I'm proud of you.

@AndreyShprengel

This comment has been minimized.

Copy link

commented Apr 10, 2017

Awesome thanks!

@selenith

This comment has been minimized.

Copy link

commented Apr 11, 2017

It Work ! You make my day 👍

@AmploDev

This comment has been minimized.

Copy link

commented Apr 12, 2017

You helped a lot! Hope I can do something back!

I had the problem that the already running audio streams were not being transferred to my bluetooth headphone. I had to manually set the running playback to my headphone in volume control.

I first had to add an ignore_fail to the execute_command to suppress errors when there are no currently playing audio streams (so the execute_command doesn't find anything, which is no problem here).

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 ignore_fail == False and (p.returncode != 0 or stderr.strip() != ''):
        raise SubprocessError('Command: %s failed with status: %s\nstderr: %s' % (cmd, p.returncode, stderr))
    return stdout

Than I added the following on line 282 to move all streams to the new 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

and than on (the now) line 347, after the line with await set_default_sink(sink), I added:

await move_streams_to_sink(sink)

This helps sending all running audio to your headphones. This is my very first python attempt, so I'm sure it can be more effective. Hopes this helpes you guys/girls!

PS: Sorry for all the edits, I'm new to github. I have made a fork to make things easier!

@chaosakos

This comment has been minimized.

Copy link

commented Apr 13, 2017

I love you :)
This is why I love linus.

@marcusbesjes

This comment has been minimized.

Copy link

commented Apr 13, 2017

works! awesome!

@flymike

This comment has been minimized.

Copy link

commented Apr 14, 2017

Thanks to @pylover for the wonderful script, @Mihara for that auto-run daemon and @dabrovnijk for the systemd service file, now my headphone is automatically set whenever I switch it on.

Just wanted to add, if you like it run as a systemd service, you have to set it in the user space, the system-wide service won't work due to pactl can't run as pid 1.

  1. Name @dabrovnijk's systemd service code to fix-bt.service and copy it into /etc/systemd/user

  2. Run
    systemctl --user enable fix-bt.service

  3. Reboot

That's it.

Update:
Found out that the systemd service is always dead after fresh boot up (It does work with manual start), so google around and here is the solution:

[Unit]
Description=Fix BT Speaker

[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/fix-bt.py

[Install]
WantedBy=multi-user.target

Just change the multi-user.target to default.target, then disable/re-enable the service. Now it really works.

[Install]
WantedBy=default.target
@pylover

This comment has been minimized.

Copy link
Owner Author

commented Apr 16, 2017

@AmploDev, Your fork is merged. Thanks a lot for enhancement.

@AmploDev

This comment has been minimized.

Copy link

commented Apr 16, 2017

@pylover You're welcome and thank you for your awesome script! I was ready to throw my headphones through my screen till you saved the day!

@bikashg

This comment has been minimized.

Copy link

commented Apr 16, 2017

What a wonderful gift! Thanks, man.

@jacopotolja

This comment has been minimized.

Copy link

commented Apr 27, 2017

I envy all of you because you know how to run a script. I made a file in my home dir i copied the script I made it executable by the properties and execute, nothing happen, sorry bothering you but I need more instructions

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Apr 27, 2017

run

chmod +x a2dp.py

then

./a2dp.py
@jvalenciag

This comment has been minimized.

Copy link

commented May 4, 2017

For people using Ubuntu 17.04 with gnome 3 with the script failing randomly this comment has the solution:

If you think you might have the same issue, first check your pulseaudio instances:

$ ps aux | grep pulseaudio
gdm 2578 4.3 0.1 2350536 12896 ? S<l 15:40 2:10 /usr/bin/pulseaudio --start --log-target=syslog
user 1533 4.3 0.1 2350536 12896 ? S<l 15:48 2:18 /usr/bin/pulseaudio --start --log-target=syslog

If you see a process owned by gdm, you can try to disable pulseaudio spawning by gdm during startup:

$ sudo nano /var/lib/gdm3/.config/pulse/client.conf
autospawn = no
daemon-binary = /bin/true

$ sudo chown gdm:gdm /var/lib/gdm3/.config/pulse/client.conf

It worked for me.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented May 6, 2017

@jvalenciag, Thanks a lot.

@HifeFish

This comment has been minimized.

Copy link

commented May 10, 2017

Thank you very much for providing this script. I had been using it manually for a few months, when I decided to automate the process about 10 days ago, unaware that it had already been done. Nevertheless, in case anyone is interested, my successful efforts to accomplish this with a udev rule are documented here: https://askubuntu.com/questions/910501/udev-rule-to-run-python-script/912838#912838

@pylover

This comment has been minimized.

Copy link
Owner Author

commented May 11, 2017

@HifeFish, Thanks

@mehdi-gital

This comment has been minimized.

Copy link

commented May 18, 2017

Thank you! It worked easy. How did you learn to do this?
I'm a py learner and to me this is amazing.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented May 18, 2017

@mehdi-gital, Thanks for completion. I owe the C language.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented May 26, 2017

@DrunkCat159, A simple workaround is to turn off and on again your Bluetooth.

@ehzawad

This comment has been minimized.

Copy link

commented Jun 1, 2017

sudo apt-get install pulseaudio-module-bluetooth

I need to run this first as dependencies @pylover

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jun 1, 2017

@ehzawad, Thanks

@MohsenHassani

This comment has been minimized.

Copy link

commented Jun 4, 2017

Thanks a lot, PyLover!!!
Getting disappointed for months over my headphone, I suddenly found your script!
It worked like a charm and I couldn't really believe it the moment I heard the A2DP sink quality; lol!
Thanks for sharing, man!

@jkhamilton62

This comment has been minimized.

Copy link

commented Jun 6, 2017

Thank you so much for this great script. I was having to constantly manually restart my bluetooth connection to my CANZ speaker I have setup on my computer running Ubuntu GNOME 16.04 LTS. This is what I did to use the script...

1/. chmod +x a2dp.py
2/. sudo ln -s /path/to/script/a2dp.py /usr/local/bin/a2dp
3/. Added a2dp to my startup applications with the MAC for the CANZ speaker.
4/. Reboot and instant joy!

Thanks again!

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jun 6, 2017

@jkhamilton62, Good trick.

@juaryR

This comment has been minimized.

Copy link

commented Jun 20, 2017

Muito Obrigado, uma mão na roda ... Cabo Verde agradece.
thank you, very useful ... Cabo verde thank you so ...

@samhains

This comment has been minimized.

Copy link

commented Jun 23, 2017

This worked great for me with Bose OE bluetooth headphones/ just make sure that your device is not on the 'Off' profile, and instead place it on the 'Headset Head Unit' profile before running the script.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jul 5, 2017

@YijunXie, You should wait about 1 minute before running this script, if not working:

Try this:
sudo service bluetooth restart

pulseaudio --kill

Turn off and on bluetooth.

Hope this works.

@mlinfoot

This comment has been minimized.

Copy link

commented Jul 5, 2017

I cannot thank you and the other contributors enough for this!!! This is the way bluetooth speakers/headsets SHOULD work - simply turn them on.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jul 8, 2017

@juaryR, você é bem-vindo.

@katp4

This comment has been minimized.

Copy link

commented Sep 12, 2017

Thank you so much!!

@Handssolow

This comment has been minimized.

Copy link

commented Oct 21, 2017

Thanks, it runs with python3 (16.04's python 3.5.2). I should have checked the earlier postings about this. I've a Blackstar Tone:Link plugged into a music centre. I've already had very intermittent success. Turning to the script, it seems to depend on the remote bt receiver being listed in pactl list cards short, which mine isn't being, so it go through the 15 times then it tries to connect. If it does connect, as expected the top toolbar bluetooth applet sign shows the lock then this in the terminal-
Setting the off profile
Disconnecting the device.
A second run of the script, the connection is made again but before it could disconnect I'd change the sound settings to A2DP and was playing music (as it is as I type this). Thus in the terminal-
Cannot find bluez_sink.E8_07_BF_21_23_DB using pacmd list-sinks. Retrying 10 more times
Device ID: bluez_card.E8_07_BF_21_23_DB
Sink: bluez_sink.E8_07_BF_21_23_DB
Updating default sink to bluez_sink.E8_07_BF_21_23_DB
Setting the off profile
Disconnecting the device.
Connecting again.
Device ID: bluez_card.E8_07_BF_21_23_DB
Setting the a2dp profile
Updating default sink to bluez_sink.E8_07_BF_21_23_DB
Moving stream 4 to sink
Exiting bluetoothctl
"Enjoy" the HiFi stereo music :)

The script looks good but the absence of my bluetooth adaptor appearing in pacmd list-sinks, looks significant and delaying connections.

@solsticedhiver

This comment has been minimized.

Copy link

commented Oct 29, 2017

my MDR-ZX220BT connects on mono HSP/HPF by default. Whatever I tries, nothing changes. So I tried a2dp.py above (changing to python 3.6) and this fixes the issue ! Fine. Thank you

I am using ubuntu 17.10 (I had no problem with 17.04 tough)

@Ranindu

This comment has been minimized.

Copy link

commented Nov 17, 2017

This is the code of life! Brilliant and thank you so much. I've been trying to connect XB950BT for about a week now.

@mahdi13

This comment has been minimized.

Copy link

commented Nov 25, 2017

Fantastic! Tnx

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Nov 25, 2017

You are welcome MR. Perfect !

@mugagambi

This comment has been minimized.

Copy link

commented Nov 28, 2017

@pylover thanks so much.This was giving me headache.Now it works flawlessly.

@BigJayToDaIzo

This comment has been minimized.

Copy link

commented Nov 30, 2017

MAN, you just solved a problem in 30 seconds that I've been toying around with for THREE DAYS. You're the man bro! Thank you!

@Hang-Hu

This comment has been minimized.

Copy link

commented Dec 1, 2017

Thanks a lot, perfect script!

@gorillaphd

This comment has been minimized.

Copy link

commented Dec 17, 2017

I managed!! It's amazing, thank you @pylover!!

@elitan

This comment has been minimized.

Copy link

commented Dec 29, 2017

How did you manage it @gorillaphd?

@rainli323

This comment has been minimized.

Copy link

commented Jan 4, 2018

Thank you!! This is the only thing that worked for me! THANKS!

@AleksueiR

This comment has been minimized.

Copy link

commented Jan 5, 2018

@oofnikj I have the same problem - headphones connecting with 'off' profile. Could you share your modifications to the script to work around that? Thanks.

@tsonne

This comment has been minimized.

Copy link

commented Jan 13, 2018

The original problem still exists on Ubuntu 16.04, but this script fixed my TaoTronics TT-BH09 (finally plays sound now)! THANKS!

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Feb 4, 2018

You're running the script by python2. issue python3.5 a2dp.py

@hpeyerl

This comment has been minimized.

Copy link

commented Mar 5, 2018

I've been annoyed by this problem for months and have wasted hour after hour trying to instrument this. I finally sat down to debug it in earnest and a google of an error message led me to a2dp.py. It 'just worked'. Thanks!

@francesco74

This comment has been minimized.

Copy link

commented Mar 30, 2018

@pylover you are my hero !
Perfect on stretch Raspberry PI 3 !!!

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Mar 31, 2018

@francesco74, Interesting, I ❤️ RPI .

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jun 6, 2018

@yochananmarqos: You have to install bluez

@p-himik

This comment has been minimized.

Copy link

commented Jun 13, 2018

@pylover FYI, bluez enabled a non-interactive mode for bluetoothctl in 0985a594. Maybe it could be used one day.

@pylover

This comment has been minimized.

Copy link
Owner Author

commented Jun 13, 2018

@p-himik, Thanks a lot.

All of this async stuff is just for waiting for an interactive result.

@wanix

This comment has been minimized.

Copy link

commented Jun 24, 2018

thanks for this script :)

@sandorkazi

This comment has been minimized.

Copy link

commented Jul 6, 2018

Almost works under Manjaro (Arch) too.

Thanks for the script, though, it was a great help.

@sherlockhomeless

This comment has been minimized.

Copy link

commented Nov 1, 2018

Works for Ubuntu 18.10 too. Well done!

@benabdullah

This comment has been minimized.

Copy link

commented Dec 28, 2018

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

@mpaluchowski

This comment has been minimized.

Copy link

commented Feb 22, 2019

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

@aaronliruns

This comment has been minimized.

Copy link

commented Feb 22, 2019

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

@R13e

This comment has been minimized.

Copy link

commented Mar 22, 2019

Works like a charm. Thanks @pylover!

@neteler

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Apr 19, 2019

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

@fmunirWorld

This comment has been minimized.

Copy link

commented May 1, 2019

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

@chrycon

This comment has been minimized.

Copy link

commented Jun 22, 2019

Linux Mint 18.3 worked PERFECTLY. what????

@DonKeyHot1

This comment has been minimized.

Copy link

commented Jun 27, 2019

Worked on ubuntu 18.04
Thanks!

@juliolopeztorres

This comment has been minimized.

Copy link

commented Jul 9, 2019

Working perfectly on Kubuntu 19.04. Thank you!

@tobiasweede

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Owner Author

commented Jul 12, 2019

@tobiasweede, Thanks in advance.

@sayalideo

This comment has been minimized.

Copy link

commented Jul 27, 2019

Thanks a lot! This worked like a charm.

@mythly

This comment has been minimized.

Copy link

commented Sep 12, 2019

u saved my day. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.