#! /usr/bin/env python # # # RF Monitor # # # Copyright 2015 Al Brown # # RF signal monitor # # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import time from wx import xrc import wx from wx.lib.agw.cubecolourdialog import CubeColourDialog from rfmonitor.constants import LEVEL_MIN, LEVEL_MAX, LEVEL_DYN_MIN, \ LEVEL_DYN_MAX from rfmonitor.events import post_event, Event, Events from rfmonitor.monitor import Monitor from rfmonitor.utils_ui import load_ui from rfmonitor.widget_meter import XrcHandlerMeter, WidgetMeter from rfmonitor.xrchandlers import XrcHandlerNumCtrl class PanelMonitor(Monitor, wx.Panel): def __init__(self, parent, eventHandler): Monitor.__init__(self, None, False, False, None, None, False, [], []) self._eventHandler = eventHandler self._isRecording = False self._isRunning = False self._isLow = True self._colours = [] pre = wx.PrePanel() self._ui = load_ui('PanelMonitor.xrc') handlerNumCtrl = XrcHandlerNumCtrl() handlerMeter = XrcHandlerMeter() self._ui.AddHandler(handlerNumCtrl) self._ui.AddHandler(handlerMeter) self._ui.LoadOnPanel(pre, parent, 'PanelMonitor') self.PostCreate(pre) self._panelColour = xrc.XRCCTRL(pre, 'panelColour') self._checkEnable = xrc.XRCCTRL(pre, 'checkEnable') self._checkAlert = xrc.XRCCTRL(pre, 'checkAlert') self._checkDynamic = xrc.XRCCTRL(pre, 'checkDynamic') self._choiceFreq = xrc.XRCCTRL(pre, 'choiceFreq') self._textSignals = xrc.XRCCTRL(pre, 'textSignals') # TODO: hackish for child in self.GetChildren(): if isinstance(child, WidgetMeter): self._meterLevel = child self._sliderThreshold = xrc.XRCCTRL(pre, 'sliderThreshold') self._buttonDel = xrc.XRCCTRL(pre, 'buttonDel') self.__set_records() self._on_del = None self._panelColour.Bind(wx.EVT_LEFT_UP, self.__on_colour) self.Bind(wx.EVT_CHECKBOX, self.__on_enable, self._checkEnable) self.Bind(wx.EVT_CHECKBOX, self.__on_alert, self._checkAlert) self.Bind(wx.EVT_CHECKBOX, self.__on_dynamic, self._checkDynamic) self.Bind(wx.EVT_CHOICE, self.__on_freq, self._choiceFreq) self.Bind(wx.EVT_SLIDER, self.__on_threshold, self._sliderThreshold) self.Bind(wx.EVT_BUTTON, self.__on_del, self._buttonDel) def __on_colour(self, _event): colourData = wx.ColourData() colourData.SetChooseFull(True) colourData.SetColour([level * 255 for level in self._colour]) for i in range(len(self._colours)): colour = [level * 255 for level in self._colours[i]] colourData.SetCustomColour(i, colour) dlg = CubeColourDialog(self, colourData) if dlg.ShowModal() == wx.ID_OK: colour = dlg.GetColourData().GetColour() colour = [level / 255. for level in colour] self.set_colour(colour) event = Event(Events.CHANGED) post_event(self._eventHandler, event) def __on_enable(self, _event): enabled = self._checkEnable.IsChecked() self.set_enabled(enabled) timestamp = time.time() if self._isRecording and self._enabled: self.start_period(timestamp) elif self._isRecording and not self._enabled: self.end_period(timestamp) event = Event(Events.CHANGED) post_event(self._eventHandler, event) def __on_alert(self, _event): self._alert = self._checkAlert.IsChecked() event = Event(Events.CHANGED) post_event(self._eventHandler, event) def __on_dynamic(self, _event=None): self.set_dynamic(self._checkDynamic.IsChecked()) event = Event(Events.CHANGED) post_event(self._eventHandler, event) def __on_freq(self, event): self._freq = float(event.GetString()) event = Event(Events.CHANGED) post_event(self._eventHandler, event) def __on_threshold(self, _event): self._threshold = self._sliderThreshold.GetValue() self._meterLevel.set_threshold(self.get_dynamic_threshold()) event = Event(Events.CHANGED) post_event(self._eventHandler, event) def __on_del(self, _event): if len(self._signals): resp = wx.MessageBox('''Remove monitor?\n''' '''The recording on this monitor will be lost''', 'Warning', wx.OK | wx.CANCEL | wx.ICON_WARNING) if resp != wx.OK: return self._on_del(self) def __enable_freq(self): self._choiceFreq.Enable(not self._isRecording and not len(self._signals)) def __set_records(self): signals = len(self._signals) label = 'Recorded: {:4d}'.format(signals) self._textSignals.SetLabel(label) self.__enable_freq() def set_callback(self, on_del): self._on_del = on_del def set_enabled(self, enabled): Monitor.set_enabled(self, enabled) self._checkEnable.SetValue(enabled) self._buttonDel.Enable(not self._enabled) self.__enable_freq() if not self._enabled: self._meterLevel.set_level(LEVEL_MIN) def set_alert(self, alert): Monitor.set_alert(self, alert) self._checkAlert.SetValue(alert) def set_freqs(self, freqs): freqs = map(str, freqs) self._choiceFreq.Clear() self._choiceFreq.AppendItems(freqs) index = len(freqs) / 2 self._freq = float(freqs[index]) self._choiceFreq.SetSelection(len(freqs) / 2) def set_frequency(self, freq): freqs = map(float, self._choiceFreq.GetItems()) try: self._choiceFreq.SetSelection(freqs.index(freq)) except ValueError: self._choiceFreq.SetSelection(len(freqs) / 2) index = self._choiceFreq.GetSelection() freq = float(self._choiceFreq.GetItems()[index]) Monitor.set_frequency(self, freq) self._signals = [] self.__set_records() def set_threshold(self, threshold): Monitor.set_threshold(self, threshold) self._meterLevel.set_threshold(self.get_dynamic_threshold()) self._sliderThreshold.SetValue(threshold) def set_dynamic(self, dynamic): Monitor.set_dynamic(self, dynamic) self._checkDynamic.SetValue(dynamic) if self._dynamic: self._sliderThreshold.SetMin(LEVEL_DYN_MIN) self._sliderThreshold.SetMax(LEVEL_DYN_MAX) else: self._sliderThreshold.SetMin(LEVEL_MIN) self._sliderThreshold.SetMax(LEVEL_MAX) self._threshold = self._sliderThreshold.GetValue() self._meterLevel.set_threshold(self.get_dynamic_threshold()) def set_noise(self, noise): if not self._dynamic: noise = None Monitor.set_noise(self, noise) def set_level(self, level, timestamp, location): threshold = self.get_dynamic_threshold() self._meterLevel.set_threshold(threshold, False) self._meterLevel.set_noise(self._noise) self._meterLevel.set_level(level) signal = None if self._isRecording: signal = Monitor.set_level(self, level, timestamp, location) if signal is not None: self.__set_records() if level >= threshold and self._isLow: self._isLow = False if self._alert: event = Event(Events.MON_ALERT) post_event(self._eventHandler, event) elif level < threshold: self._isLow = True return signal def set_recording(self, isRecording, timestamp): self._isRecording = isRecording self.__enable_freq() if isRecording and self._enabled: self.start_period(timestamp) elif not self._isRecording and self._enabled: self.end_period(timestamp) def set_signals(self, signals): Monitor.set_signals(self, signals) self.__set_records() def set_colour(self, colour): self._colour = colour if colour is not None: wxColour = [level * 255 for level in colour] self._panelColour.SetBackgroundColour(wxColour) self._panelColour.Refresh() def set_colours(self, colours): self._colours = colours def clear(self): Monitor.clear(self) self.__set_records() if __name__ == '__main__': print 'Please run rfmonitor.py' exit(1)