mirror of https://github.com/tuhiproject/tuhi.git
dbus: limit StartSearch to one client only
Basically copied from the device's Listening approach. While it's possible to have multiple clients searching at the same time it's a niche case and the effort at fixing the race conditions that come from that is likely not worth the effort. Let's add multiple simultaneous clients when we have a real need for it.pull/27/head
parent
cce63d267b
commit
cfa4aca2df
25
README.md
25
README.md
|
@ -52,11 +52,28 @@ org.freedesktop.tuhi1.Manager
|
||||||
initialization is independent of the Bluetooth pairing process. A Tuhi
|
initialization is independent of the Bluetooth pairing process. A Tuhi
|
||||||
paired device may or may not be paired over Bluetooth.
|
paired device may or may not be paired over Bluetooth.
|
||||||
|
|
||||||
|
Property: Searching (b)
|
||||||
|
Indicates whether the daemon is currently searching for pairable devices.
|
||||||
|
|
||||||
|
This property is set to True when a StartSearching() request initiates
|
||||||
|
the search for device connections. When the StartSearching() request
|
||||||
|
completes upon timeout, or when StopSearching() is called, the property
|
||||||
|
is set to False.
|
||||||
|
|
||||||
|
When a pariable device is found, the PairableDevice signal is sent to
|
||||||
|
the caller that initiated the search process.
|
||||||
|
|
||||||
|
Read-only
|
||||||
|
|
||||||
Method: StartSearch() -> ()
|
Method: StartSearch() -> ()
|
||||||
Start searching for available devices in pairing mode for an
|
Start searching for available devices in pairing mode for an
|
||||||
unspecified timeout. When the timeout expires or an error occurs, a
|
unspecified timeout. When the timeout expires or an error occurs, a
|
||||||
SearchStopped signal is sent indicating success or error.
|
SearchStopped signal is sent indicating success or error.
|
||||||
|
|
||||||
|
If a client that successfully initated a listening process calls
|
||||||
|
StartSearching() again, that call is ignored and no signal is
|
||||||
|
generated for that call.
|
||||||
|
|
||||||
Method: StopSearch() -> ()
|
Method: StopSearch() -> ()
|
||||||
Stop listening to available devices in pairing mode. If called after
|
Stop listening to available devices in pairing mode. If called after
|
||||||
StartSearch() and before a SearchStopped signal has been received,
|
StartSearch() and before a SearchStopped signal has been received,
|
||||||
|
@ -72,7 +89,8 @@ org.freedesktop.tuhi1.Manager
|
||||||
Signal: PairableDevice(o)
|
Signal: PairableDevice(o)
|
||||||
Indicates that a device is available for pairing. This signal may be
|
Indicates that a device is available for pairing. This signal may be
|
||||||
sent after a StartSearch() call and before SearchStopped(). This
|
sent after a StartSearch() call and before SearchStopped(). This
|
||||||
signal is sent once per available device.
|
signal is sent once per available device and only to the client that
|
||||||
|
initiated the search process with StartSearch.
|
||||||
|
|
||||||
When this signal is sent, a org.freedesktop.tuhi1.Device object was
|
When this signal is sent, a org.freedesktop.tuhi1.Device object was
|
||||||
created, the object path is the argument to this signal.
|
created, the object path is the argument to this signal.
|
||||||
|
@ -90,6 +108,11 @@ org.freedesktop.tuhi1.Manager
|
||||||
successful termination of the search process, either when a device
|
successful termination of the search process, either when a device
|
||||||
has been paired or the timeout expired.
|
has been paired or the timeout expired.
|
||||||
|
|
||||||
|
If the errno is -EAGAIN, the daemon is already searching for devices
|
||||||
|
on behalf of another client. In this case, this client should wait for
|
||||||
|
the Searching property to change and StartSearching() once the
|
||||||
|
property is set to False.
|
||||||
|
|
||||||
Once this signal has been sent, all devices announced through
|
Once this signal has been sent, all devices announced through
|
||||||
PairableDevice signals should be considered invalidated. Attempting to
|
PairableDevice signals should be considered invalidated. Attempting to
|
||||||
Pair() one of the devices after the SearchStopped() signal may result
|
Pair() one of the devices after the SearchStopped() signal may result
|
||||||
|
|
|
@ -25,6 +25,10 @@ INTROSPECTION_XML = """
|
||||||
<annotation name='org.freedesktop.DBus.Property.EmitsChangedSignal' value='true'/>
|
<annotation name='org.freedesktop.DBus.Property.EmitsChangedSignal' value='true'/>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property type='ao' name='Searching' access='read'>
|
||||||
|
<annotation name='org.freedesktop.DBus.Property.EmitsChangedSignal' value='true'/>
|
||||||
|
</property>
|
||||||
|
|
||||||
<method name='StartSearch'>
|
<method name='StartSearch'>
|
||||||
<annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>
|
<annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>
|
||||||
</method>
|
</method>
|
||||||
|
@ -332,6 +336,34 @@ class TuhiDBusServer(GObject.Object):
|
||||||
self._is_searching = False
|
self._is_searching = False
|
||||||
self._searching_client = None
|
self._searching_client = None
|
||||||
|
|
||||||
|
@GObject.Property
|
||||||
|
def is_searching(self):
|
||||||
|
return self._is_searching
|
||||||
|
|
||||||
|
@is_searching.setter
|
||||||
|
def is_searching(self, value):
|
||||||
|
if self._is_searching == value:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._is_searching = value
|
||||||
|
|
||||||
|
props = GLib.VariantBuilder(GLib.VariantType('a{sv}'))
|
||||||
|
de = GLib.Variant.new_dict_entry(GLib.Variant.new_string('Searching'),
|
||||||
|
GLib.Variant.new_variant(
|
||||||
|
GLib.Variant.new_boolean(value)))
|
||||||
|
props.add_value(de)
|
||||||
|
props = props.end()
|
||||||
|
inval_props = GLib.VariantBuilder(GLib.VariantType('as'))
|
||||||
|
inval_props = inval_props.end()
|
||||||
|
|
||||||
|
self._connection.emit_signal(None, self.objpath,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"PropertiesChanged",
|
||||||
|
GLib.Variant.new_tuple(
|
||||||
|
GLib.Variant.new_string(INTF_MANAGER),
|
||||||
|
props,
|
||||||
|
inval_props))
|
||||||
|
|
||||||
def _bus_aquired(self, connection, name):
|
def _bus_aquired(self, connection, name):
|
||||||
introspection = Gio.DBusNodeInfo.new_for_xml(INTROSPECTION_XML)
|
introspection = Gio.DBusNodeInfo.new_for_xml(INTROSPECTION_XML)
|
||||||
intf = introspection.lookup_interface(INTF_MANAGER)
|
intf = introspection.lookup_interface(INTF_MANAGER)
|
||||||
|
@ -342,6 +374,7 @@ class TuhiDBusServer(GObject.Object):
|
||||||
self._property_read_cb,
|
self._property_read_cb,
|
||||||
self._property_write_cb)
|
self._property_write_cb)
|
||||||
self._connection = connection
|
self._connection = connection
|
||||||
|
self.objpath = BASE_PATH
|
||||||
|
|
||||||
def _bus_name_aquired(self, connection, name):
|
def _bus_name_aquired(self, connection, name):
|
||||||
logger.debug('Bus name aquired')
|
logger.debug('Bus name aquired')
|
||||||
|
@ -367,6 +400,8 @@ class TuhiDBusServer(GObject.Object):
|
||||||
|
|
||||||
if propname == 'Devices':
|
if propname == 'Devices':
|
||||||
return GLib.Variant.new_objv([d.objpath for d in self._devices if d.paired])
|
return GLib.Variant.new_objv([d.objpath for d in self._devices if d.paired])
|
||||||
|
elif propname == 'Searching':
|
||||||
|
return GLib.Variant.new_boolean(self.is_searching)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -374,11 +409,19 @@ class TuhiDBusServer(GObject.Object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _start_search(self, connection, sender):
|
def _start_search(self, connection, sender):
|
||||||
# FIXME: need to handle multiple clients here
|
if self.is_searching:
|
||||||
if self._is_searching:
|
logger.debug("Already searching")
|
||||||
|
|
||||||
|
# silently ignore it for the current client but send EAGAIN to
|
||||||
|
# other clients
|
||||||
|
if sender != self._searching_client[0]:
|
||||||
|
status = GLib.Variant.new_int32(-errno.EAGAIN)
|
||||||
|
status = GLib.Variant.new_tuple(status)
|
||||||
|
connection.emit_signal(sender, self.objpath, INTF_MANAGER,
|
||||||
|
"SearchStopped", status)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._is_searching = True
|
self.is_searching = True
|
||||||
|
|
||||||
s = connection.signal_subscribe(sender='org.freedesktop.DBus',
|
s = connection.signal_subscribe(sender='org.freedesktop.DBus',
|
||||||
interface_name='org.freedesktop.DBus',
|
interface_name='org.freedesktop.DBus',
|
||||||
|
@ -405,12 +448,12 @@ class TuhiDBusServer(GObject.Object):
|
||||||
self._stop_search(connection, user_data)
|
self._stop_search(connection, user_data)
|
||||||
|
|
||||||
def _stop_search(self, connection, sender):
|
def _stop_search(self, connection, sender):
|
||||||
# FIXME: need to handle multiple clients here
|
if not self.is_searching or sender != self._searching_client[0]:
|
||||||
if not self._is_searching or sender != self._searching_client[0]:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
connection.signal_unsubscribe(self._searching_client[1])
|
connection.signal_unsubscribe(self._searching_client[1])
|
||||||
self._is_searching = False
|
self.is_searching = False
|
||||||
|
self._searching_client = None
|
||||||
self.emit("search-stop-requested")
|
self.emit("search-stop-requested")
|
||||||
|
|
||||||
def _on_search_stop(self, status):
|
def _on_search_stop(self, status):
|
||||||
|
@ -418,10 +461,11 @@ class TuhiDBusServer(GObject.Object):
|
||||||
Called by whoever handles the search-start-requested signal
|
Called by whoever handles the search-start-requested signal
|
||||||
"""
|
"""
|
||||||
logger.debug("Search has stopped")
|
logger.debug("Search has stopped")
|
||||||
self._is_searching = False
|
self.is_searching = False
|
||||||
status = GLib.Variant.new_int32(status)
|
status = GLib.Variant.new_int32(status)
|
||||||
status = GLib.Variant.new_tuple(status)
|
status = GLib.Variant.new_tuple(status)
|
||||||
self._connection.emit_signal(None, BASE_PATH, INTF_MANAGER,
|
self._connection.emit_signal(self._searching_client[0],
|
||||||
|
BASE_PATH, INTF_MANAGER,
|
||||||
"SearchStopped", status)
|
"SearchStopped", status)
|
||||||
self._searching_client = None
|
self._searching_client = None
|
||||||
|
|
||||||
|
@ -466,6 +510,7 @@ class TuhiDBusServer(GObject.Object):
|
||||||
|
|
||||||
def _emit_pairable_signal(self, device):
|
def _emit_pairable_signal(self, device):
|
||||||
arg = GLib.Variant.new_object_path(device.objpath)
|
arg = GLib.Variant.new_object_path(device.objpath)
|
||||||
self._connection.emit_signal(None, BASE_PATH, INTF_MANAGER,
|
self._connection.emit_signal(self._searching_client[0],
|
||||||
|
BASE_PATH, INTF_MANAGER,
|
||||||
"PairableDevice",
|
"PairableDevice",
|
||||||
GLib.Variant.new_tuple(arg))
|
GLib.Variant.new_tuple(arg))
|
||||||
|
|
Loading…
Reference in New Issue