controls/DiscoveryPanel.py
changeset 3938 fc4af5685aa3
parent 3935 bc51b5a2daa9
equal deleted inserted replaced
3937:e13543d716b6 3938:fc4af5685aa3
    23 # along with this program; if not, write to the Free Software
    23 # along with this program; if not, write to the Free Software
    24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    25 
    25 
    26 
    26 
    27 import socket
    27 import socket
       
    28 import weakref
    28 import wx
    29 import wx
    29 import wx.lib.mixins.listctrl as listmix
    30 import wx.lib.mixins.listctrl as listmix
    30 from zeroconf import ServiceBrowser, Zeroconf, get_all_addresses
    31 from zeroconf import ServiceBrowser, Zeroconf, get_all_addresses
    31 
    32 
    32 service_type = '_Beremiz._tcp.local.'
    33 service_type = '_Beremiz._tcp.local.'
    33 
    34 
       
    35 class ZeroConfListenerClass:
       
    36     def __init__(self, dialog):
       
    37         self.dialog = weakref.ref(dialog)
       
    38         self.ZeroConfInstance = Zeroconf()
       
    39         self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
       
    40 
       
    41     def clean(self):
       
    42         if self.Browser is not None:
       
    43             self.Browser.cancel()
       
    44             self.Browser = None
       
    45         if  self.ZeroConfInstance is not None:
       
    46             self.ZeroConfInstance.close()
       
    47             self.ZeroConfInstance = None
       
    48 
       
    49     def __del__(self):
       
    50         self.clean()
       
    51 
       
    52     def update_service(self, zeroconf, _type, name):
       
    53         self.remove_service(zeroconf, _type, name)
       
    54         self.add_service(zeroconf, _type, name)
       
    55 
       
    56     def add_service(self, zeroconf, _type, name):
       
    57         info = self.ZeroConfInstance.get_service_info(_type, name)
       
    58         if info is None:
       
    59             return
       
    60         typename = info.properties.get(b"protocol", None).decode()
       
    61         ip = str(info.parsed_addresses()[0])
       
    62         port = info.port
       
    63 
       
    64         wx.CallAfter(self._add_service, typename, ip, port, name)
       
    65 
       
    66     def _add_service(self, typename, ip, port, name):
       
    67         dialog = self.dialog()
       
    68         if not dialog: return
       
    69         dialog._addService(typename, ip, port, name)
       
    70 
       
    71     def remove_service(self, zeroconf, _type, name):
       
    72         wx.CallAfter(self._remove_service, name)
       
    73 
       
    74     def _remove_service(self, name):
       
    75         dialog = self.dialog()
       
    76         if not dialog: return
       
    77         dialog._removeService(name)
    34 
    78 
    35 class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    79 class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    36     def __init__(self, parent, name, pos=wx.DefaultPosition,
    80     def __init__(self, parent, name, pos=wx.DefaultPosition,
    37                  size=wx.DefaultSize, style=0):
    81                  size=wx.DefaultSize, style=0):
    38         wx.ListCtrl.__init__(self, parent, wx.ID_ANY, pos, size, style, name=name)
    82         wx.ListCtrl.__init__(self, parent, wx.ID_ANY, pos, size, style, name=name)
   114 
   158 
   115         self.itemDataMap = {}
   159         self.itemDataMap = {}
   116         self.nextItemId = 0
   160         self.nextItemId = 0
   117 
   161 
   118         self.URI = None
   162         self.URI = None
   119         self.Browser = None
       
   120         self.ZeroConfInstance = None
       
   121 
   163 
   122         self.RefreshList()
   164         self.RefreshList()
   123         self.LatestSelection = None
   165         self.LatestSelection = None
   124 
   166 
   125         self.IfacesMonitorState = None
   167         self.IfacesMonitorState = None
   126         self.IfacesMonitorTimer = wx.Timer(self)
   168         self.IfacesMonitorTimer = wx.Timer(self)
   127         self.IfacesMonitorTimer.Start(2000)
   169         self.IfacesMonitorTimer.Start(2000)
       
   170         self.ZeroConfListener = None
   128         self.Bind(wx.EVT_TIMER, self.IfacesMonitor, self.IfacesMonitorTimer)
   171         self.Bind(wx.EVT_TIMER, self.IfacesMonitor, self.IfacesMonitorTimer)
   129 
   172 
   130     def _cleanup(self):
   173     def _cleanup(self):
   131         if self.IfacesMonitorTimer is not None:
   174         if self.IfacesMonitorTimer is not None:
   132             self.IfacesMonitorTimer.Stop()
   175             self.IfacesMonitorTimer.Stop()
   133             self.IfacesMonitorTimer = None
   176             self.IfacesMonitorTimer = None
   134         if self.Browser is not None:
   177         if self.ZeroConfListener is not None:
   135             self.Browser.cancel()
   178             self.ZeroConfListener.clean()
   136             self.Browser = None
   179             self.ZeroConfListener = None
   137         if self.ZeroConfInstance is not None:
       
   138             self.ZeroConfInstance.close()
       
   139             self.ZeroConfInstance = None
       
   140 
   180 
   141     def __del__(self):
   181     def __del__(self):
   142         self._cleanup()
   182         self._cleanup()
   143 
   183 
   144     def Destroy(self):
   184     def Destroy(self):
   158             self.IfacesMonitorState = NewState
   198             self.IfacesMonitorState = NewState
   159         event.Skip()
   199         event.Skip()
   160 
   200 
   161     def RefreshList(self):
   201     def RefreshList(self):
   162         self.ServicesList.DeleteAllItems()
   202         self.ServicesList.DeleteAllItems()
   163         if self.Browser is not None:
   203         self.ZeroConfListener = ZeroConfListenerClass(self)
   164             self.Browser.cancel()
       
   165         if self.ZeroConfInstance is not None:
       
   166             self.ZeroConfInstance.close()
       
   167         self.ZeroConfInstance = Zeroconf()
       
   168         self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
       
   169 
   204 
   170     def OnRefreshButton(self, event):
   205     def OnRefreshButton(self, event):
   171         self.RefreshList()
   206         self.RefreshList()
   172 
   207 
   173     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
   208     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
   177     def getColumnText(self, index, col):
   212     def getColumnText(self, index, col):
   178         item = self.ServicesList.GetItem(index, col)
   213         item = self.ServicesList.GetItem(index, col)
   179         return item.GetText()
   214         return item.GetText()
   180 
   215 
   181     def OnItemSelected(self, event):
   216     def OnItemSelected(self, event):
   182         self.SetURI(event.m_itemIndex)
   217         self.SetURI(event.GetIndex())
   183         event.Skip()
   218         event.Skip()
   184 
   219 
   185     def OnItemActivated(self, event):
   220     def OnItemActivated(self, event):
   186         self.SetURI(event.m_itemIndex)
   221         self.SetURI(event.GetIndex())
   187         self.parent.EndModal(wx.ID_OK)
   222         self.parent.EndModal(wx.ID_OK)
   188         event.Skip()
   223         event.Skip()
   189 
   224 
   190 #    def SetURI(self, idx):
   225 #    def SetURI(self, idx):
   191 #        connect_type = self.getColumnText(idx, 1)
   226 #        connect_type = self.getColumnText(idx, 1)
   209             #     svcname = self.getColumnText(self.LatestSelection, 0)
   244             #     svcname = self.getColumnText(self.LatestSelection, 0)
   210             #     connect_type = self.getColumnText(self.LatestSelection, 1)
   245             #     connect_type = self.getColumnText(self.LatestSelection, 1)
   211             #     return str("MDNS://%s" % svcname)
   246             #     return str("MDNS://%s" % svcname)
   212         return None
   247         return None
   213 
   248 
   214     def remove_service(self, zeroconf, _type, name):
       
   215         wx.CallAfter(self._removeService, name)
       
   216 
       
   217     def _removeService(self, name):
   249     def _removeService(self, name):
   218         '''
   250         '''
   219         called when a service with the desired type goes offline.
   251         called when a service with the desired type goes offline.
   220         '''
   252         '''
   221 
   253 
   229 
   261 
   230             if item_name == name:
   262             if item_name == name:
   231                 self.ServicesList.DeleteItem(idx)
   263                 self.ServicesList.DeleteItem(idx)
   232                 break
   264                 break
   233 
   265 
   234     def add_service(self, zeroconf, _type, name):
   266 
   235         wx.CallAfter(self._addService, _type, name)
   267     def _addService(self, typename, ip, port, name):
   236 
       
   237     def _addService(self, _type, name):
       
   238         '''
   268         '''
   239         called when a service with the desired type is discovered.
   269         called when a service with the desired type is discovered.
   240         '''
   270         '''
   241         info = self.ZeroConfInstance.get_service_info(_type, name)
       
   242         if info is None:
       
   243             return
       
   244         svcname = name.split(".")[0]
   271         svcname = name.split(".")[0]
   245         typename = info.properties.get("protocol", None)
       
   246         ip = str(socket.inet_ntoa(info.address))
       
   247         port = info.port
       
   248 
   272 
   249         num_items = self.ServicesList.GetItemCount()
   273         num_items = self.ServicesList.GetItemCount()
   250 
   274 
   251         # display the new data in the list
   275         # display the new data in the list
   252         new_item = self.ServicesList.InsertStringItem(num_items, svcname)
   276         new_item = self.ServicesList.InsertStringItem(num_items, svcname)