diff options
author | PastLeo | 2019-02-05 09:40:04 +0800 |
---|---|---|
committer | PastLeo | 2019-02-05 15:30:50 +0800 |
commit | b7c148d5b6ce211470c194268062a76fd00b1714 (patch) | |
tree | 1287fb135645269e1c110d7d98dd54d2cd9567a3 | |
download | aur-b7c148d5b6ce211470c194268062a76fd00b1714.tar.gz |
finish 0.1-1 with my first PKGBUILD
-rw-r--r-- | .SRCINFO | 22 | ||||
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | LICENSE | 21 | ||||
-rw-r--r-- | PKGBUILD | 26 | ||||
-rw-r--r-- | README.md | 20 | ||||
-rwxr-xr-x | fix-bt-a2dp.rb | 152 | ||||
-rw-r--r-- | fix-bt-a2dp.service | 10 | ||||
-rw-r--r-- | fix-bt-a2dp.udev-rules | 1 |
8 files changed, 255 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..21a5666df363 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,22 @@ +pkgbase = fix-bt-a2dp + pkgdesc = Fix Bluetooth A2DP using systemd and udev rule + pkgver = 0.1 + pkgrel = 1 + url = https://github.com/pastleo/fix-bt-a2dp + arch = any + license = MIT + depends = ruby + depends = bluez + depends = bluez-utils + depends = pulseaudio + depends = pulseaudio-bluetooth + optdepends = libnotify + source = fix-bt-a2dp.rb + source = fix-bt-a2dp.service + source = fix-bt-a2dp.udev-rules + md5sums = f63057d641cb3c2e005653acdd6a4af9 + md5sums = 24aa8ecab3f87b3cd6f8a318d314b27d + md5sums = 53997fa84224bae44cdd1c4b5f88550f + +pkgname = fix-bt-a2dp + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..e612735d8821 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/src +/pkg +/*.pkg.tar.xz diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..9a4b17a22e17 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 PastLeo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..3840cf0d64e4 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,26 @@ +# Maintainer: PastLeo <chgu82837@gmail.com> +pkgname=fix-bt-a2dp +pkgver=0.1 +pkgrel=1 +pkgdesc="Fix Bluetooth A2DP using systemd and udev rule" +arch=('any') +url="https://github.com/pastleo/fix-bt-a2dp" +license=('MIT') +depends=('ruby' 'bluez' 'bluez-utils' 'pulseaudio' 'pulseaudio-bluetooth') +optdepends=('libnotify') +source=( + 'fix-bt-a2dp.rb' + 'fix-bt-a2dp.service' + 'fix-bt-a2dp.udev-rules' +) +md5sums=( + 'f63057d641cb3c2e005653acdd6a4af9' + '24aa8ecab3f87b3cd6f8a318d314b27d' + '53997fa84224bae44cdd1c4b5f88550f' +) + +package() { + install -D -m755 ./fix-bt-a2dp.rb "$pkgdir/usr/bin/fix-bt-a2dp" + install -D -m644 ./fix-bt-a2dp.service "$pkgdir/usr/lib/systemd/system/fix-bt-a2dp.service" + install -D -m644 ./fix-bt-a2dp.udev-rules "$pkgdir/usr/lib/udev/rules.d/90-fix-bt-a2dp.rules" +} diff --git a/README.md b/README.md new file mode 100644 index 000000000000..4a72f2744a74 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +Fix Bluetooth Audio A2DP Sinks +=== + +Fix Bluetooth A2DP using systemd and udev rule + +> a rewrite from https://gist.github.com/EHfive/c4f1218a75f95b076f0387403246de78, avoid blocking other BT dev connecting + +## Usage + +install this AUR first: + +``` +yay -S fix-bt-a2dp +``` + +run this command with root to set GUI session owner: + +``` +/usr/bin/fix-bt-a2dp set-user [user] +``` diff --git a/fix-bt-a2dp.rb b/fix-bt-a2dp.rb new file mode 100755 index 000000000000..cd049f6f4315 --- /dev/null +++ b/fix-bt-a2dp.rb @@ -0,0 +1,152 @@ +#!/usr/bin/env ruby + +RUNNING_FILE = '/tmp/.fix-bt-a2dp.running' +USER_FILE = '/etc/.fix-bt-a2dp.user' +ROOT_UID = 0 + +if system("which notify-send &> /dev/null") + def gui_notify(msg) + puts "notify-send: #{msg}" + `notify-send '#{msg}'` + end +else + def gui_notify(msg) + puts "notify-send: #{msg}" + end +end + +def command_failed(name, stdout) + if stdout.strip.empty? + raise "#{name} failed" + else + raise "#{name} failed:\n#{stdout}" + end +end + +def bluetoothctl_info_value(v) + return true if v.downcase == 'yes' + return false if v.downcase == 'no' + v +end + +def bluetoothctl_info(mac) + Hash[ + `bluetoothctl info #{mac}`.lines.drop(1).map do |line| + line.split(':', 2).map(&:strip) + end.map do |k, v| + [k.downcase.to_sym, v] + end.group_by do |k, _v| + k + end.map do |k, v| + if v.count == 1 + [k, bluetoothctl_info_value(v[0][1])] + else + [k, v.map {|vv| vv[1]}] + end + end + ] + # will return {} if dev of mac not found +end + +def have_audio_sink?(uuid_values) + uuid_value = uuid_values.kind_of?(Array) ? uuid_values.join : uuid_values + uuid_value.downcase.gsub(' ', '').include?("audiosink") +end + +def enable_a2dp(name, mac, bluez_mac, info) + puts "enabling #{name}, mac: #{mac}" + + puts ">> bluetoothctl connect #{mac}" + bluetoothctl_connect_out = `bluetoothctl connect #{mac}` + unless $?.success? && bluetoothctl_connect_out.downcase.include?('successful') + command_failed('bluetoothctl connect', bluetoothctl_connect_out) + end + + sleep 1 + + puts ">> pacmd set-card-profile bluez_card.#{bluez_mac} a2dp_sink" + set_card_profile_out = `pacmd set-card-profile bluez_card.#{bluez_mac} a2dp_sink` + unless $?.success? && set_card_profile_out == '' + command_failed('pacmd set-card-profile', set_card_profile_out) + end + + puts "a2dp enabled for #{name}!" + gui_notify("#{name} connected and set to A2DP") +end + +def scan_enable_a2dp + bt_devs = `bluetoothctl devices` + command_failed('`bluetoothctl devices`', bt_devs) unless $?.success? + + pacmd_sinks = `pacmd list-sinks` + command_failed('`pacmd list-sinks`', pacmd_sinks) unless $?.success? + + bt_sinks_no_a2dp = bt_devs.lines.map do |bt_dev_line| + bt_dev_line.split(' ') + end.map do |_, mac, name| + [name, mac, "#{mac.gsub(':', '_')}", bluetoothctl_info(mac)] + end.keep_if do |name, mac, bluez_mac, info| + !info.empty? && + info[:paired] && + info[:trusted] && + !info[:blocked] && + info[:connected] && + have_audio_sink?(info[:uuid]) && + !pacmd_sinks.include?("bluez_sink.#{bluez_mac}.a2dp_sink") + end + + if bt_sinks_no_a2dp.empty? + puts "No bluetooth devices with audio sink and without A2DP" + else + puts "Bluetooth devices with audio sink and without A2DP: #{bt_sinks_no_a2dp.map(&:first).join(', ')}" + bt_sinks_no_a2dp.each do |name, mac, bluez_mac, info| + begin + enable_a2dp(name, mac, bluez_mac, info) + rescue => e + STDERR.puts e + end + end + puts "done!" + end +end + +def main + if File.exist?(RUNNING_FILE) + puts "already running at pid #{File.read(RUNNING_FILE)} (#{RUNNING_FILE} exists)...exit" + return 0 + end + return_code = 1 + File.open(RUNNING_FILE, 'w') {|f| f.write(Process.pid.to_s) } + puts "waiting for 5 seconds..." + sleep 5 + + begin + scan_enable_a2dp + return_code = 0 + rescue => e + STDERR.puts e + end + + `rm #{RUNNING_FILE}` + return_code +end + +if Process.uid == ROOT_UID + if ARGV[0] == 'set-user' + `rm -f #{USER_FILE}` + user = ARGV[1].strip + uid = `id -u #{user}`.strip + xdg_runtime_dir = ENV['XDG_RUNTIME_DIR'] || "/run/user/#{uid}" + File.open(USER_FILE, 'w') {|f| f.write("#{user}:#{xdg_runtime_dir}") } + exit 0 + elsif Process.uid == ROOT_UID && File.exist?(USER_FILE) + user, xdg_runtime_dir = File.read(USER_FILE).strip.split(':') + puts ">> XDG_RUNTIME_DIR=#{xdg_runtime_dir} su #{user} -c #{__FILE__}" + exec({'XDG_RUNTIME_DIR' => xdg_runtime_dir}, "su #{user} -c #{__FILE__}") + else + STDERR.puts "As root, please run this first:\n\t#{__FILE__} set-user [user]" + exit 1 + end +else + exit main +end diff --git a/fix-bt-a2dp.service b/fix-bt-a2dp.service new file mode 100644 index 000000000000..a563c5221347 --- /dev/null +++ b/fix-bt-a2dp.service @@ -0,0 +1,10 @@ +[Unit] +Description=Fix Bluetooth A2DP + +[Service] +Type=simple +ExecStart=/usr/bin/fix-bt-a2dp +StandardOutput=journal + +[Install] +WantedBy=multi-user.target diff --git a/fix-bt-a2dp.udev-rules b/fix-bt-a2dp.udev-rules new file mode 100644 index 000000000000..a83943c062c0 --- /dev/null +++ b/fix-bt-a2dp.udev-rules @@ -0,0 +1 @@ +SUBSYSTEM=="bluetooth", ACTION=="add", RUN+="/usr/bin/systemctl start fix-bt-a2dp" |