@@ -53,7 +53,7 @@ def emit(self, record):
53
53
54
54
__all__ = [
55
55
"Zeroconf" , "ServiceInfo" , "ServiceBrowser" ,
56
- "Error" , "InterfaceChoice" ,
56
+ "Error" , "InterfaceChoice" , "ServiceStateChange" ,
57
57
]
58
58
59
59
@@ -921,6 +921,33 @@ def run(self):
921
921
self .zc .cache .remove (record )
922
922
923
923
924
+ class Signal (object ):
925
+ def __init__ (self ):
926
+ self ._handlers = []
927
+
928
+ def fire (self , ** kwargs ):
929
+ for h in list (self ._handlers ):
930
+ h (** kwargs )
931
+
932
+ @property
933
+ def registration_interface (self ):
934
+ return SignalRegistrationInterface (self ._handlers )
935
+
936
+
937
+ class SignalRegistrationInterface (object ):
938
+
939
+ def __init__ (self , handlers ):
940
+ self ._handlers = handlers
941
+
942
+ def register_handler (self , handler ):
943
+ self ._handlers .append (handler )
944
+ return self
945
+
946
+ def unregister_handler (self , handler ):
947
+ self ._handlers .remove (handler )
948
+ return self
949
+
950
+
924
951
class ServiceBrowser (threading .Thread ):
925
952
926
953
"""Used to browse for a service of a specific type.
@@ -929,13 +956,12 @@ class ServiceBrowser(threading.Thread):
929
956
remove_service() methods called when this browser
930
957
discovers changes in the services availability."""
931
958
932
- def __init__ (self , zc , type , listener ):
959
+ def __init__ (self , zc , type_ , handlers ):
933
960
"""Creates a browser for a specific type"""
934
961
threading .Thread .__init__ (self )
935
962
self .daemon = True
936
963
self .zc = zc
937
- self .type = type
938
- self .listener = listener
964
+ self .type = type_
939
965
self .services = {}
940
966
self .next_time = current_time_millis ()
941
967
self .delay = _BROWSER_TIME
@@ -946,10 +972,28 @@ def __init__(self, zc, type, listener):
946
972
self .zc .add_listener (self , DNSQuestion (self .type , _TYPE_PTR , _CLASS_IN ))
947
973
self .start ()
948
974
975
+ self ._service_state_changed = Signal ()
976
+ for h in handlers :
977
+ self .service_state_changed .register_handler (h )
978
+
979
+ @property
980
+ def service_state_changed (self ):
981
+ return self ._service_state_changed .registration_interface
982
+
949
983
def update_record (self , zc , now , record ):
950
984
"""Callback invoked by Zeroconf when new information arrives.
951
985
952
986
Updates information required by browser in the Zeroconf cache."""
987
+
988
+ def enqueue_callback (state_change , name ):
989
+ self ._handlers_to_call .append (
990
+ lambda zeroconf : self ._service_state_changed .fire (
991
+ zeroconf = zeroconf ,
992
+ service_type = self .type ,
993
+ name = name ,
994
+ state_change = state_change ,
995
+ ))
996
+
953
997
if record .type == _TYPE_PTR and record .name == self .type :
954
998
expired = record .is_expired (now )
955
999
service_key = record .alias .lower ()
@@ -958,15 +1002,13 @@ def update_record(self, zc, now, record):
958
1002
except KeyError :
959
1003
if not expired :
960
1004
self .services [service_key ] = record
961
- self ._handlers_to_call .append (
962
- lambda x : self .listener .add_service (x , self .type , record .alias ))
1005
+ enqueue_callback (ServiceStateChange .Added , record .alias )
963
1006
else :
964
1007
if not expired :
965
1008
old_record .reset_ttl (record )
966
1009
else :
967
1010
del self .services [service_key ]
968
- self ._handlers_to_call .append (
969
- lambda x : self .listener .remove_service (x , self .type , record .alias ))
1011
+ enqueue_callback (ServiceStateChange .Removed , record .alias )
970
1012
return
971
1013
972
1014
expires = record .get_expiration_time (75 )
@@ -1197,6 +1239,12 @@ class InterfaceChoice(enum.Enum):
1197
1239
All = 2
1198
1240
1199
1241
1242
+ @enum .unique
1243
+ class ServiceStateChange (enum .Enum ):
1244
+ Added = 1
1245
+ Removed = 2
1246
+
1247
+
1200
1248
HOST_ONLY_NETWORK_MASK = '255.255.255.255'
1201
1249
1202
1250
0 commit comments