280 lines
9.7 KiB
Python
Executable File
280 lines
9.7 KiB
Python
Executable File
#! /usr/bin/python3
|
|
|
|
from __future__ import print_function
|
|
from __future__ import division
|
|
from __future__ import absolute_import
|
|
from __future__ import unicode_literals
|
|
|
|
import os.path
|
|
import sys
|
|
import signal
|
|
import dbus
|
|
from dbus.mainloop.glib import DBusGMainLoop
|
|
from blueman.Constants import *
|
|
import gi
|
|
gi.require_version("Gtk", "3.0")
|
|
from gi.repository import Gtk
|
|
from gi.repository import GObject
|
|
from blueman.bluez.BlueZInterface import BlueZInterface
|
|
|
|
#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)
|
|
|
|
from blueman.Functions import *
|
|
from blueman.main.Device import Device
|
|
from blueman.bluez.Device import Device as BluezDevice
|
|
from blueman.gui.manager.ManagerDeviceList import ManagerDeviceList
|
|
from blueman.gui.manager.ManagerToolbar import ManagerToolbar
|
|
from blueman.gui.manager.ManagerMenu import ManagerMenu
|
|
from blueman.gui.manager.ManagerStats import ManagerStats
|
|
from blueman.gui.manager.ManagerProgressbar import ManagerProgressbar
|
|
from blueman.main.Config import Config
|
|
|
|
from blueman.gui.MessageArea import MessageArea
|
|
|
|
from blueman.main.PluginManager import PluginManager
|
|
import blueman.plugins.manager
|
|
from blueman.plugins.ManagerPlugin import ManagerPlugin
|
|
|
|
DBusGMainLoop(set_as_default=True)
|
|
|
|
# Workaround introspection bug, gnome bug 622084
|
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
|
|
enable_rgba_colormap()
|
|
|
|
|
|
class Blueman:
|
|
def __init__(self):
|
|
|
|
self.Builder = Gtk.Builder()
|
|
self.Builder.set_translation_domain("blueman")
|
|
self.Builder.add_from_file(UI_PATH + "/manager-main.ui")
|
|
|
|
self.window = self.Builder.get_object("window")
|
|
|
|
self.Plugins = PluginManager(ManagerPlugin, blueman.plugins.manager, None)
|
|
self.Plugins.Load()
|
|
|
|
vbox = self.Builder.get_object("vbox1")
|
|
area = MessageArea()
|
|
vbox.pack_start(area, False, False, 0)
|
|
vbox.reorder_child(area, 3)
|
|
|
|
# Add padding for resize grip or it will overlap
|
|
if self.window.get_has_resize_grip():
|
|
align3 = self.Builder.get_object("alignment3")
|
|
top, bottom, left, right = align3.get_padding()
|
|
align3.set_padding(top, bottom, left, right + 10)
|
|
|
|
def do_present(time):
|
|
if self.window.props.visible:
|
|
self.window.present_with_time(time)
|
|
|
|
check_single_instance("blueman-manager", do_present)
|
|
|
|
def on_window_delete(window, event):
|
|
w, h = self.window.get_size()
|
|
x, y = self.window.get_position()
|
|
self.Config["window-properties"] = [w, h, x, y]
|
|
Gtk.main_quit()
|
|
|
|
def on_latest_last_changed(ignored1, ignored2):
|
|
try: self.List.DisplayKnownDevices(autoselect=True)
|
|
except: pass
|
|
|
|
def on_bt_status_changed(status):
|
|
if not status:
|
|
self.window.hide()
|
|
check_bluetooth_status(_("Bluetooth needs to be turned on for the device manager to function"),
|
|
lambda: Gtk.main_quit())
|
|
else:
|
|
self.window.show()
|
|
|
|
def on_bluez_name_owner_changed(owner):
|
|
dprint('org.bluez owner changed to ', owner)
|
|
if owner == '':
|
|
self.window.hide()
|
|
d = Gtk.MessageDialog(self.window, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE)
|
|
d.props.icon_name = "blueman"
|
|
d.props.text = _("Connection to BlueZ failed")
|
|
|
|
d.props.secondary_text = _(
|
|
"Bluez daemon is not running, blueman-manager cannot continue.\nThis probably means that there were no Bluetooth adapters detected or Bluetooth daemon was not started.")
|
|
|
|
d.run()
|
|
d.destroy()
|
|
try:
|
|
exit(1)
|
|
except:
|
|
Gtk.main_quit()
|
|
else:
|
|
|
|
setup_icon_path()
|
|
|
|
self.Config = Config("org.blueman.general")
|
|
|
|
try:
|
|
self.Applet = AppletService()
|
|
except:
|
|
print("Blueman applet needs to be running")
|
|
exit()
|
|
try:
|
|
if not self.Applet.GetBluetoothStatus():
|
|
on_bt_status_changed(False)
|
|
except:
|
|
pass
|
|
self.Applet.Handle("BluetoothStatusChanged", on_bt_status_changed)
|
|
|
|
self.window.connect("delete-event", on_window_delete)
|
|
self.window.props.icon_name = "blueman"
|
|
|
|
w, h, x, y = self.Config["window-properties"]
|
|
if w and h: self.window.resize(w, h)
|
|
if x and y: self.window.move(x, y)
|
|
|
|
sw = self.Builder.get_object("scrollview")
|
|
|
|
self.List = ManagerDeviceList(adapter=self.Config["last-adapter"], inst=self)
|
|
|
|
self.List.show()
|
|
sw.add(self.List)
|
|
|
|
self.Toolbar = ManagerToolbar(self)
|
|
self.Menu = ManagerMenu(self)
|
|
self.Stats = ManagerStats(self)
|
|
|
|
if self.List.IsValidAdapter():
|
|
self.List.DisplayKnownDevices(autoselect=True)
|
|
|
|
self.List.connect("adapter-changed", self.on_adapter_changed)
|
|
|
|
self.Config.connect("changed::latest-last", on_latest_last_changed)
|
|
|
|
toolbar2 = self.Builder.get_object("toolbar2")
|
|
statusbar = self.Builder.get_object("statusbar")
|
|
|
|
self.Config.bind_to_widget("show-toolbar", toolbar2, "visible")
|
|
self.Config.bind_to_widget("show-statusbar", statusbar, "visible")
|
|
|
|
self.window.show()
|
|
|
|
dbus.SystemBus().watch_name_owner('org.bluez', on_bluez_name_owner_changed)
|
|
Gtk.main()
|
|
|
|
def on_adapter_changed(self, list, adapter):
|
|
if adapter != None:
|
|
self.List.DisplayKnownDevices(autoselect=True)
|
|
|
|
def add_device(self, device):
|
|
# BlueZ 4 only!
|
|
|
|
def ok(device):
|
|
dev = Device(device)
|
|
self.List.add_device(dev)
|
|
prog.finalize()
|
|
MessageArea.close()
|
|
|
|
def err(*args):
|
|
prog.finalize()
|
|
MessageArea.show_message(e_(str(args[0])))
|
|
|
|
adapter = self.List.Adapter
|
|
|
|
prog = ManagerProgressbar(self, text=_("Adding"))
|
|
prog.connect("cancelled", lambda x: self.List.Adapter.get_interface().CancelDeviceCreation(device.Address))
|
|
|
|
prog.start()
|
|
adapter.create_device(device.Address, reply_handler=ok, error_handler=err)
|
|
|
|
def inquiry(self):
|
|
def prop_changed(List, adapter, key_value):
|
|
key, value = key_value
|
|
if key == "Discovering" and not value:
|
|
prog.finalize()
|
|
self.List.disconnect(s1)
|
|
self.List.disconnect(s2)
|
|
|
|
def on_progress(list, frac):
|
|
if abs(1.0 - frac) <= 0.00001:
|
|
if not prog.started():
|
|
prog.start()
|
|
else:
|
|
prog.fraction(frac)
|
|
|
|
prog = ManagerProgressbar(self, text=_("Searching"))
|
|
prog.connect("cancelled", lambda x: self.List.StopDiscovery())
|
|
try:
|
|
self.List.DiscoverDevices()
|
|
except Exception as e:
|
|
prog.finalize()
|
|
MessageArea.show_message(e_(e))
|
|
|
|
s1 = self.List.connect("discovery-progress", on_progress)
|
|
s2 = self.List.connect("adapter-property-changed", prop_changed)
|
|
|
|
def setup(self, device):
|
|
command = "blueman-assistant --device=%s" % device.Address
|
|
launch(command, None, False, "blueman", _("Bluetooth Assistant"))
|
|
|
|
def bond(self, device):
|
|
if BlueZInterface.get_interface_version()[0] < 5:
|
|
def ok(device):
|
|
dev = Device(BluezDevice(device))
|
|
self.List.add_device(dev)
|
|
prog.message(_("Success"))
|
|
MessageArea.close()
|
|
|
|
def err(*args):
|
|
dprint(args)
|
|
prog.message(_("Failure"))
|
|
MessageArea.show_message(e_(str(args[0])))
|
|
|
|
applet = AppletService()
|
|
|
|
address = device.get_properties()["Address"]
|
|
adapter = self.List.Adapter
|
|
|
|
prog = ManagerProgressbar(self, text=_("Pairing"))
|
|
prog.connect("cancelled", lambda x: applet.CancelDeviceCreation(adapter.get_object_path(), device.Address))
|
|
prog.start()
|
|
|
|
name = adapter_path_to_name(self.List.Adapter.get_object_path())
|
|
|
|
applet.CreateDevice(adapter.get_object_path(), device.Address, True, Gtk.get_current_event_time(),
|
|
reply_handler=ok, error_handler=err, timeout=120)
|
|
else:
|
|
self.List.Adapter.find_device(device.Address).pair()
|
|
|
|
def adapter_properties(self):
|
|
adapter = self.List.Adapter
|
|
name = os.path.basename(adapter.get_object_path())
|
|
launch("blueman-adapters", None, False, "blueman", _("Adapter Preferences"))
|
|
|
|
def toggle_trust(self, device):
|
|
props = device.get_properties()
|
|
device.Trusted = not device.Trusted
|
|
|
|
def send(self, device, File=None):
|
|
adapter = self.List.Adapter
|
|
props = adapter.get_properties()
|
|
|
|
command = "blueman-sendto --source=%s --device=%s" % (props["Address"], device.Address)
|
|
launch(command, None, False, "blueman", _("File Sender"))
|
|
|
|
def remove(self, device):
|
|
self.List.Adapter.remove_device(device.Device)
|
|
|
|
def browse(self, device):
|
|
launch("blueman-browse -d %s" % device.Address)
|
|
|
|
def disconnect(self, device, *args, **kwargs):
|
|
applet = AppletService()
|
|
applet.DisconnectDevice(device.get_object_path(), *args, **kwargs)
|
|
|
|
|
|
set_proc_title()
|
|
Blueman()
|