aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorPastLeo2019-02-05 09:40:04 +0800
committerPastLeo2019-02-05 15:30:50 +0800
commitb7c148d5b6ce211470c194268062a76fd00b1714 (patch)
tree1287fb135645269e1c110d7d98dd54d2cd9567a3
downloadaur-b7c148d5b6ce211470c194268062a76fd00b1714.tar.gz
finish 0.1-1 with my first PKGBUILD
-rw-r--r--.SRCINFO22
-rw-r--r--.gitignore3
-rw-r--r--LICENSE21
-rw-r--r--PKGBUILD26
-rw-r--r--README.md20
-rwxr-xr-xfix-bt-a2dp.rb152
-rw-r--r--fix-bt-a2dp.service10
-rw-r--r--fix-bt-a2dp.udev-rules1
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"