mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-28 13:16:41 +00:00
bluetooth-audio: avoid LE Settings Addon crash
This commit is contained in:
parent
3524972190
commit
d2ea00a971
@ -1,3 +1,6 @@
|
|||||||
|
102
|
||||||
|
- Avoid LibreELEC Settings addon crash
|
||||||
|
|
||||||
101
|
101
|
||||||
- Fix log errors
|
- Fix log errors
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
PKG_NAME="bluetooth-audio"
|
PKG_NAME="bluetooth-audio"
|
||||||
PKG_VERSION="0"
|
PKG_VERSION="0"
|
||||||
PKG_REV="101"
|
PKG_REV="102"
|
||||||
PKG_ARCH="any"
|
PKG_ARCH="any"
|
||||||
PKG_LICENSE="GPL"
|
PKG_LICENSE="GPL"
|
||||||
PKG_SITE=""
|
PKG_SITE=""
|
||||||
|
110
packages/addons/service/bluetooth-audio/source/bin/dbusservice.py
Executable file
110
packages/addons/service/bluetooth-audio/source/bin/dbusservice.py
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/python2
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import dbus
|
||||||
|
import dbus.mainloop.glib
|
||||||
|
import gobject
|
||||||
|
import time
|
||||||
|
|
||||||
|
gobject.threads_init()
|
||||||
|
|
||||||
|
class BluetoothAudioClient(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.devices = {}
|
||||||
|
self.signal_added = None
|
||||||
|
self.signal_removed = None
|
||||||
|
|
||||||
|
self._setup_loop()
|
||||||
|
self._setup_bus()
|
||||||
|
self._setup_signals()
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
|
||||||
|
self.signal_added.remove()
|
||||||
|
self.signal_removed.remove()
|
||||||
|
|
||||||
|
self._loop.quit()
|
||||||
|
|
||||||
|
def _setup_loop(self):
|
||||||
|
|
||||||
|
self._loop = gobject.MainLoop()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self._loop.run()
|
||||||
|
|
||||||
|
def _setup_bus(self):
|
||||||
|
|
||||||
|
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||||
|
self._bus = dbus.SystemBus()
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
|
||||||
|
self.signal_added = self._bus.add_signal_receiver(handler_function=self.switch_audio,
|
||||||
|
signal_name='InterfacesAdded',
|
||||||
|
dbus_interface='org.freedesktop.DBus.ObjectManager',
|
||||||
|
bus_name='org.bluez',
|
||||||
|
member_keyword='signal')
|
||||||
|
|
||||||
|
self.signal_removed = self._bus.add_signal_receiver(handler_function=self.switch_audio,
|
||||||
|
signal_name='InterfacesRemoved',
|
||||||
|
dbus_interface='org.freedesktop.DBus.ObjectManager',
|
||||||
|
bus_name='org.bluez',
|
||||||
|
member_keyword='signal')
|
||||||
|
|
||||||
|
def switch_audio(self, *args, **kwargs):
|
||||||
|
|
||||||
|
device_path = args[0]
|
||||||
|
|
||||||
|
try:
|
||||||
|
if kwargs['signal'] == 'InterfacesAdded':
|
||||||
|
|
||||||
|
self.devices[device_path] = {
|
||||||
|
'Connected': '',
|
||||||
|
'Device': '',
|
||||||
|
'Class': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
device = self._bus.get_object('org.bluez', device_path)
|
||||||
|
device_iface = dbus.Interface(device, dbus.PROPERTIES_IFACE)
|
||||||
|
self.devices[device_path]['Device'] = device_iface.Get('org.bluez.MediaTransport1', 'Device')
|
||||||
|
|
||||||
|
audio_device_path = self._bus.get_object('org.bluez', self.devices[device_path]['Device'])
|
||||||
|
audio_device_iface = dbus.Interface(audio_device_path, dbus.PROPERTIES_IFACE)
|
||||||
|
self.devices[device_path]['Class'] = audio_device_iface.Get('org.bluez.Device1', 'Class')
|
||||||
|
self.devices[device_path]['Connected'] = audio_device_iface.Get('org.bluez.Device1', 'Connected')
|
||||||
|
|
||||||
|
if self.devices[device_path]['Class'] & (1 << 21):
|
||||||
|
print('bluetooth')
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
elif kwargs['signal'] == 'InterfacesRemoved':
|
||||||
|
if self.devices[device_path]['Device'] is not None and self.devices[device_path]['Class'] & (1 << 21):
|
||||||
|
audio_device_path = self._bus.get_object('org.bluez', self.devices[device_path]['Device'])
|
||||||
|
audio_device_iface = dbus.Interface(audio_device_path, dbus.PROPERTIES_IFACE)
|
||||||
|
self.devices[device_path]['Connected'] = audio_device_iface.Get('org.bluez.Device1', 'Connected')
|
||||||
|
|
||||||
|
while self.devices[device_path]['Connected']:
|
||||||
|
self.devices[device_path]['Connected'] = audio_device_iface.Get('org.bluez.Device1', 'Connected')
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
for path in self.devices:
|
||||||
|
if self.devices[path]['Connected'] and self.devices[path]['Class'] & (1 << 21):
|
||||||
|
return
|
||||||
|
|
||||||
|
print('default')
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
except (TypeError, KeyError, dbus.exceptions.DBusException) as e:
|
||||||
|
print('%s: ' % unicode(e), file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
client = BluetoothAudioClient()
|
||||||
|
|
||||||
|
client.run()
|
||||||
|
|
||||||
|
del BluetoothAudioClient
|
@ -1,19 +1,15 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
|
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
|
||||||
|
|
||||||
import dbus
|
|
||||||
import dbus.mainloop.glib
|
|
||||||
import gobject
|
|
||||||
import json
|
import json
|
||||||
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import time
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
|
|
||||||
__addon__ = xbmcaddon.Addon()
|
__addon__ = xbmcaddon.Addon()
|
||||||
__addonid__ = __addon__.getAddonInfo('id')
|
__addonid__ = __addon__.getAddonInfo('id')
|
||||||
|
__addonpath__ = xbmc.translatePath(xbmcaddon.Addon().getAddonInfo('path')).decode('utf-8')
|
||||||
gobject.threads_init()
|
|
||||||
|
|
||||||
class KodiFunctions(object):
|
class KodiFunctions(object):
|
||||||
|
|
||||||
@ -63,103 +59,38 @@ class BluetoothAudioClient(object):
|
|||||||
|
|
||||||
xbmc.log('%s: starting add-on' % __addonid__, xbmc.LOGNOTICE)
|
xbmc.log('%s: starting add-on' % __addonid__, xbmc.LOGNOTICE)
|
||||||
|
|
||||||
self.devices = {}
|
|
||||||
self.signal_added = None
|
|
||||||
self.signal_removed = None
|
|
||||||
|
|
||||||
self.kodi = KodiFunctions()
|
self.kodi = KodiFunctions()
|
||||||
|
self.path = __addonpath__ + '/bin/dbusservice.py'
|
||||||
|
|
||||||
|
self.service = subprocess.Popen([self.path], stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
self._thread = threading.Thread(target=self.loop)
|
||||||
|
self._thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
def loop(self):
|
||||||
|
|
||||||
|
while True:
|
||||||
|
line = self.service.stdout.readline()
|
||||||
|
if line == '':
|
||||||
|
break
|
||||||
|
if line == 'bluetooth\n':
|
||||||
|
self.kodi.select_pulse()
|
||||||
|
continue
|
||||||
|
if line == 'default\n':
|
||||||
|
self.kodi.select_default()
|
||||||
|
continue
|
||||||
|
xbmc.log('%s: unexpected input: %s' % (__addonid__, line), xbmc.LOGERROR)
|
||||||
|
|
||||||
self._setup_loop()
|
|
||||||
self._setup_bus()
|
|
||||||
self._setup_signals()
|
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
|
|
||||||
xbmc.log('%s: stopping add-on' % __addonid__, xbmc.LOGNOTICE)
|
xbmc.log('%s: stopping add-on' % __addonid__, xbmc.LOGNOTICE)
|
||||||
|
|
||||||
|
self.service.terminate()
|
||||||
|
self._thread.join()
|
||||||
self.kodi.select_default()
|
self.kodi.select_default()
|
||||||
|
|
||||||
self.signal_added.remove()
|
|
||||||
self.signal_removed.remove()
|
|
||||||
|
|
||||||
self._loop.quit()
|
|
||||||
|
|
||||||
def _setup_loop(self):
|
|
||||||
|
|
||||||
self._loop = gobject.MainLoop()
|
|
||||||
|
|
||||||
self._thread = threading.Thread(target=self._loop.run)
|
|
||||||
self._thread.start()
|
|
||||||
|
|
||||||
def _setup_bus(self):
|
|
||||||
|
|
||||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
|
||||||
self._bus = dbus.SystemBus()
|
|
||||||
|
|
||||||
def _setup_signals(self):
|
|
||||||
|
|
||||||
self.signal_added = self._bus.add_signal_receiver(handler_function=self.switch_audio,
|
|
||||||
signal_name='InterfacesAdded',
|
|
||||||
dbus_interface='org.freedesktop.DBus.ObjectManager',
|
|
||||||
bus_name='org.bluez',
|
|
||||||
member_keyword='signal')
|
|
||||||
|
|
||||||
self.signal_removed = self._bus.add_signal_receiver(handler_function=self.switch_audio,
|
|
||||||
signal_name='InterfacesRemoved',
|
|
||||||
dbus_interface='org.freedesktop.DBus.ObjectManager',
|
|
||||||
bus_name='org.bluez',
|
|
||||||
member_keyword='signal')
|
|
||||||
|
|
||||||
def switch_audio(self, *args, **kwargs):
|
|
||||||
|
|
||||||
device_path = args[0]
|
|
||||||
|
|
||||||
try:
|
|
||||||
if kwargs['signal'] == 'InterfacesAdded':
|
|
||||||
|
|
||||||
self.devices[device_path] = {
|
|
||||||
'Connected': '',
|
|
||||||
'Device': '',
|
|
||||||
'Class': '',
|
|
||||||
}
|
|
||||||
|
|
||||||
device = self._bus.get_object('org.bluez', device_path)
|
|
||||||
device_iface = dbus.Interface(device, dbus.PROPERTIES_IFACE)
|
|
||||||
self.devices[device_path]['Device'] = device_iface.Get('org.bluez.MediaTransport1', 'Device')
|
|
||||||
|
|
||||||
audio_device_path = self._bus.get_object('org.bluez', self.devices[device_path]['Device'])
|
|
||||||
audio_device_iface = dbus.Interface(audio_device_path, dbus.PROPERTIES_IFACE)
|
|
||||||
self.devices[device_path]['Class'] = audio_device_iface.Get('org.bluez.Device1', 'Class')
|
|
||||||
self.devices[device_path]['Connected'] = audio_device_iface.Get('org.bluez.Device1', 'Connected')
|
|
||||||
|
|
||||||
if self.devices[device_path]['Class'] & (1 << 21):
|
|
||||||
xbmc.log('%s: bluetooth audio device connected' % __addonid__, xbmc.LOGNOTICE)
|
|
||||||
xbmc.log('%s: switching to bluetooth audio device' % __addonid__, xbmc.LOGNOTICE)
|
|
||||||
self.kodi.select_pulse()
|
|
||||||
|
|
||||||
elif kwargs['signal'] == 'InterfacesRemoved':
|
|
||||||
if self.devices[device_path]['Device'] is not None and self.devices[device_path]['Class'] & (1 << 21):
|
|
||||||
audio_device_path = self._bus.get_object('org.bluez', self.devices[device_path]['Device'])
|
|
||||||
audio_device_iface = dbus.Interface(audio_device_path, dbus.PROPERTIES_IFACE)
|
|
||||||
self.devices[device_path]['Connected'] = audio_device_iface.Get('org.bluez.Device1', 'Connected')
|
|
||||||
|
|
||||||
while self.devices[device_path]['Connected']:
|
|
||||||
self.devices[device_path]['Connected'] = audio_device_iface.Get('org.bluez.Device1', 'Connected')
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
xbmc.log('%s: bluetooth audio device disconnected' % __addonid__, xbmc.LOGNOTICE)
|
|
||||||
xbmc.log('%s: checking for other connected devices' % __addonid__, xbmc.LOGNOTICE)
|
|
||||||
|
|
||||||
for path in self.devices:
|
|
||||||
if self.devices[path]['Connected'] and self.devices[path]['Class'] & (1 << 21):
|
|
||||||
xbmc.log('%s: found connected bluetooth audio device' % __addonid__, xbmc.LOGNOTICE)
|
|
||||||
return
|
|
||||||
|
|
||||||
xbmc.log('%s: switching to default audio device' % __addonid__, xbmc.LOGNOTICE)
|
|
||||||
self.kodi.select_default()
|
|
||||||
|
|
||||||
except (TypeError, KeyError, dbus.exceptions.DBusException) as e:
|
|
||||||
xbmc.log('%s: ' % __addonid__ + unicode(e), xbmc.LOGERROR)
|
|
||||||
|
|
||||||
class BluetoothMonitor(xbmc.Monitor):
|
class BluetoothMonitor(xbmc.Monitor):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user