/usr/bin/blueman-adapters is in blueman 2.0.4-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | #! /usr/bin/python3
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import Pango
import os.path
import sys
import signal
#support running uninstalled
_dirname = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if os.path.exists(os.path.join(_dirname, "CHANGELOG.md")):
sys.path.insert(0, _dirname)
import blueman.bluez as Bluez
from blueman.Constants import *
from blueman.Functions import *
from blueman.main.SignalTracker import SignalTracker
enable_rgba_colormap()
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
DBusGMainLoop(set_as_default=True)
# Workaround introspection bug, gnome bug 622084
signal.signal(signal.SIGINT, signal.SIG_DFL)
class BluemanAdapters:
def __init__(self, selected_hci_dev):
setup_icon_path()
self.bus = dbus.SystemBus()
self.bus.watch_name_owner('org.bluez', self.on_dbus_name_owner_change)
builder = Gtk.Builder()
builder.set_translation_domain("blueman")
builder.add_from_file(UI_PATH + "/adapters.ui")
self.dialog = builder.get_object("dialog")
check_single_instance("blueman-adapters", lambda time: self.dialog.present_with_time(time))
check_bluetooth_status(_("Bluetooth needs to be turned on for the adapter manager to work"), lambda: exit())
self.dialog.props.icon_name = "blueman-device"
self.dialog.connect("response", self.on_dialog_response)
self.notebook = builder.get_object("notebook")
self.tabs = {}
try:
self.signals = SignalTracker()
self.manager = Bluez.Manager()
self.signals.Handle("bluez", self.manager, self.on_adapter_added, 'AdapterAdded')
adapters = self.manager.list_adapters()
for adapter in adapters:
self.add_to_notebook(adapter)
except Exception as e:
print(e)
self.manager = None
#fixme: show error dialog and exit
#activate a particular tab according to command line option
if selected_hci_dev is not None:
if selected_hci_dev in self.tabs:
hci_dev_num = int(selected_hci_dev[3:])
self.notebook.set_current_page(hci_dev_num)
else:
print('Error: the selected adapter does not exist')
self.dialog.show()
Gtk.main()
def on_dialog_response(self, dialog, response_id):
for hci, settings in self.tabs.items():
if settings['changed']:
settings['adapter'].set_name(settings['name'])
Gtk.main_quit()
def on_adapter_added(self, adapter_path):
def on_property_changed(name, value):
if name == 'Powered' and value:
adapter.unhandle_signal(on_property_changed, "PropertyChanged")
self.add_to_notebook(adapter)
adapter = Bluez.Adapter(adapter_path)
adapter.handle_signal(on_property_changed, "PropertyChanged")
def on_dbus_name_owner_change(self, owner):
print('org.bluez owner changed to '+owner)
if owner == '':
self.manager = None
#fixme: show error dialog and exit
def build_adapter_tab(self, adapter):
adapter_settings = {}
def on_property_changed(name, value):
if name == 'Powered':
if not value:
self.remove_from_notebook(adapter)
else:
self.add_to_notebook(adapter)
elif name == "Discoverable":
if value == 0:
hidden_radio.set_active(True)
def on_hidden_toggle(radio):
if not radio.props.active:
return
adapter_settings['discoverable'] = False
adapter.set('Discoverable', False)
hscale.set_sensitive(False)
#we need to triger "format-value" signal
hscale.set_value(1)
hscale.set_value(0)
def on_always_toggle(radio):
if not radio.props.active:
return
adapter_settings['discoverable'] = True
adapter.set('Discoverable', True)
hscale.set_sensitive(False)
#we need to triger "format-value" signal
hscale.set_value(1)
hscale.set_value(0)
def on_temporary_toggle(radio):
if not radio.props.active:
return
adapter_settings['discoverable'] = True
adapter.set('Discoverable', True)
hscale.set_sensitive(True)
hscale.set_value(3)
def on_scale_format_value(scale, value):
if value == 0:
if adapter_settings['discoverable']:
return _("Always")
else:
return _("Hidden")
else:
return gettext.ngettext("%d Minute", "%d Minutes", value) % (value)
def on_scale_value_changed(scale):
val = scale.get_value()
print('value: '+str(val))
if val == 0 and adapter_settings['discoverable']:
always_radio.props.active = True
timeout = int(val * 60)
adapter.set('DiscoverableTimeout', timeout)
def on_name_changed(entry):
adapter_settings['name'] = entry.get_text()
adapter_settings['changed'] = True
props = adapter.get_properties()
adapter_settings['adapter'] = adapter
adapter_settings['signals'] = SignalTracker()
adapter_settings['signals'].Handle(adapter, on_property_changed, "PropertyChanged")
adapter_settings['address'] = props['Address']
adapter_settings['name'] = adapter.get_name()
adapter_settings['discoverable'] = props['Discoverable']
#we use count timeout in minutes
adapter_settings['discoverable_timeout'] = props['DiscoverableTimeout'] / 60
adapter_settings['changed'] = False
builder = Gtk.Builder()
builder.set_translation_domain("blueman")
builder.add_from_file(UI_PATH + "/adapters-tab.ui")
adapter_settings['vbox'] = builder.get_object("vbox1")
hscale = builder.get_object("hscale")
hscale.set_range(0, 30)
hscale.set_increments(1, 1)
if adapter_settings['discoverable']:
hscale.set_value(adapter_settings['discoverable_timeout'])
hscale.set_sensitive(adapter_settings['discoverable_timeout'] > 0)
adapter_settings['signals'].Handle(hscale, "format-value", on_scale_format_value)
adapter_settings['signals'].Handle(hscale, "value-changed", on_scale_value_changed)
hidden_radio = builder.get_object("hidden1")
if not adapter_settings['discoverable']:
hidden_radio.set_active(True)
adapter_settings['signals'].Handle(hidden_radio, "toggled", on_hidden_toggle)
always_radio = builder.get_object("always")
if adapter_settings['discoverable'] and adapter_settings['discoverable_timeout'] == 0:
always_radio.set_active(True)
adapter_settings['signals'].Handle(always_radio, "toggled", on_always_toggle)
temporary_radio = builder.get_object("temporary")
if adapter_settings['discoverable'] and adapter_settings['discoverable_timeout'] > 0:
temporary_radio.set_active(True)
adapter_settings['signals'].Handle(temporary_radio, "toggled", on_temporary_toggle)
name_entry = builder.get_object("name_entry")
name_entry.set_text(adapter_settings['name'])
adapter_settings['signals'].Handle(name_entry, "changed", on_name_changed)
return adapter_settings
def add_to_notebook(self, adapter):
hci_dev = os.path.basename(adapter.get_object_path())
hci_dev_num = int(hci_dev[3:])
if not hci_dev in self.tabs:
self.tabs[hci_dev] = self.build_adapter_tab(adapter)
else:
if self.tabs[hci_dev]['visible']:
return
#might need to update settings at this point
settings = self.tabs[hci_dev]
settings['visible'] = True
name = settings['name']
if name == '':
name = _('Adapter') + ' %d' % (hci_dev_num + 1)
label = Gtk.Label(label=name)
label.set_max_width_chars(20)
label.props.hexpand = True
label.set_ellipsize(Pango.EllipsizeMode.END)
self.notebook.insert_page(settings['vbox'], label, hci_dev_num)
def remove_from_notebook(self, adapter):
hci_dev = os.path.basename(adapter.get_object_path())
hci_dev_num = int(hci_dev[3:])
self.tabs[hci_dev]['visible'] = False
self.notebook.remove_page(hci_dev_num)
#leave actual tab contents intact in case adapter becomes present once again
if __name__ == '__main__':
set_proc_title()
adapter_name = None
if len(sys.argv) > 1:
adapter_name = sys.argv[1]
BluemanAdapters(adapter_name)
|