text: #!/usr/bin/env python3
  # -*- coding: utf-8 -*-
  
  #
  # SPDX-License-Identifier: GPL-3.0
  #
  # GNU Radio Python Flow Graph
  # Title: Osc
  # GNU Radio version: 3.8.2.0
  
  from distutils.version import StrictVersion
  
  if __name__ == '__main__':
      import ctypes
      import sys
      if sys.platform.startswith('linux'):
          try:
              x11 = ctypes.cdll.LoadLibrary('libX11.so')
              x11.XInitThreads()
          except:
              print("Warning: failed to XInitThreads()")
  
  from PyQt5 import Qt
  from gnuradio import qtgui
  from gnuradio.filter import firdes
  import sip
  from gnuradio import analog
  from gnuradio import audio
  from gnuradio import blocks
  from gnuradio import filter
  from gnuradio import gr
  import sys
  import signal
  from argparse import ArgumentParser
  from gnuradio.eng_arg import eng_float, intx
  from gnuradio import eng_notation
  from gnuradio.qtgui import Range, RangeWidget
  
  from gnuradio import qtgui
  
  class osc(gr.top_block, Qt.QWidget):
  
      def __init__(self):
          gr.top_block.__init__(self, "Osc")
          Qt.QWidget.__init__(self)
          self.setWindowTitle("Osc")
          qtgui.util.check_set_qss()
          try:
              self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
          except:
              pass
          self.top_scroll_layout = Qt.QVBoxLayout()
          self.setLayout(self.top_scroll_layout)
          self.top_scroll = Qt.QScrollArea()
          self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
          self.top_scroll_layout.addWidget(self.top_scroll)
          self.top_scroll.setWidgetResizable(True)
          self.top_widget = Qt.QWidget()
          self.top_scroll.setWidget(self.top_widget)
          self.top_layout = Qt.QVBoxLayout(self.top_widget)
          self.top_grid_layout = Qt.QGridLayout()
          self.top_layout.addLayout(self.top_grid_layout)
  
          self.settings = Qt.QSettings("GNU Radio", "osc")
  
          try:
              if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                  self.restoreGeometry(self.settings.value("geometry").toByteArray())
              else:
                  self.restoreGeometry(self.settings.value("geometry"))
          except:
              pass
  
          ##################################################
          # Variables
          ##################################################
          self.samp_rate = samp_rate = 48000
          self.balance = balance = 0
          self.ToneLevel = ToneLevel = 0.5
          self.ToneFreq = ToneFreq = 1000
  
          ##################################################
          # Blocks
          ##################################################
          self._balance_range = Range(-1, +1, .01, 0, 200)
          self._balance_win = RangeWidget(self._balance_range, self.set_balance, 'balance', "counter_slider", float)
          self.top_grid_layout.addWidget(self._balance_win)
          self._ToneLevel_range = Range(0, 1, .01, 0.5, 200)
          self._ToneLevel_win = RangeWidget(self._ToneLevel_range, self.set_ToneLevel, 'ToneLevel', "counter_slider", float)
          self.top_grid_layout.addWidget(self._ToneLevel_win)
          self._ToneFreq_range = Range(50, 10000, 100, 1000, 200)
          self._ToneFreq_win = RangeWidget(self._ToneFreq_range, self.set_ToneFreq, 'ToneFreq', "counter_slider", float)
          self.top_grid_layout.addWidget(self._ToneFreq_win)
          self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
              1024, #size
              samp_rate, #samp_rate
              "", #name
              2 #number of inputs
          )
          self.qtgui_time_sink_x_0.set_update_time(0.10)
          self.qtgui_time_sink_x_0.set_y_axis(-1, 1)
  
          self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
  
          self.qtgui_time_sink_x_0.enable_tags(True)
          self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
          self.qtgui_time_sink_x_0.enable_autoscale(False)
          self.qtgui_time_sink_x_0.enable_grid(False)
          self.qtgui_time_sink_x_0.enable_axis_labels(True)
          self.qtgui_time_sink_x_0.enable_control_panel(False)
          self.qtgui_time_sink_x_0.enable_stem_plot(False)
  
  
          labels = ['', '', '', '', '',
              '', '', '', '', '']
          widths = [1, 1, 1, 1, 1,
              1, 1, 1, 1, 1]
          colors = ['blue', 'red', 'green', 'black', 'cyan',
              'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
          alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
              1.0, 1.0, 1.0, 1.0, 1.0]
          styles = [1, 1, 1, 1, 1,
              1, 1, 1, 1, 1]
          markers = [-1, -1, -1, -1, -1,
              -1, -1, -1, -1, -1]
  
  
          for i in range(2):
              if len(labels[i]) == 0:
                  self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
              else:
                  self.qtgui_time_sink_x_0.set_line_label(i, labels[i])
              self.qtgui_time_sink_x_0.set_line_width(i, widths[i])
              self.qtgui_time_sink_x_0.set_line_color(i, colors[i])
              self.qtgui_time_sink_x_0.set_line_style(i, styles[i])
              self.qtgui_time_sink_x_0.set_line_marker(i, markers[i])
              self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i])
  
          self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget)
          self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
          self.low_pass_filter_0 = filter.fir_filter_ccf(
              1,
              firdes.low_pass(
                  1,
                  samp_rate,
                  3500,
                  100,
                  firdes.WIN_BLACKMAN,
                  6.76))
          self.blocks_multiply_const_vxx_1 = blocks.multiply_const_ff(1 + balance/2)
          self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(1 - balance/2)
          self.blocks_complex_to_float_0 = blocks.complex_to_float(1)
          self.audio_sink_0 = audio.sink(samp_rate, 'hw:RadioHatCodec,0', True)
          self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, ToneFreq, ToneLevel, 0, 0)
  
  
  
          ##################################################
          # Connections
          ##################################################
          self.connect((self.analog_sig_source_x_0, 0), (self.low_pass_filter_0, 0))
          self.connect((self.blocks_complex_to_float_0, 1), (self.blocks_multiply_const_vxx_0, 0))
          self.connect((self.blocks_complex_to_float_0, 0), (self.blocks_multiply_const_vxx_1, 0))
          self.connect((self.blocks_multiply_const_vxx_0, 0), (self.audio_sink_0, 0))
          self.connect((self.blocks_multiply_const_vxx_0, 0), (self.qtgui_time_sink_x_0, 0))
          self.connect((self.blocks_multiply_const_vxx_1, 0), (self.audio_sink_0, 1))
          self.connect((self.blocks_multiply_const_vxx_1, 0), (self.qtgui_time_sink_x_0, 1))
          self.connect((self.low_pass_filter_0, 0), (self.blocks_complex_to_float_0, 0))
  
  
      def closeEvent(self, event):
          self.settings = Qt.QSettings("GNU Radio", "osc")
          self.settings.setValue("geometry", self.saveGeometry())
          event.accept()
  
      def get_samp_rate(self):
          return self.samp_rate
  
      def set_samp_rate(self, samp_rate):
          self.samp_rate = samp_rate
          self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
          self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate, 3500, 100, firdes.WIN_BLACKMAN, 6.76))
          self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
  
      def get_balance(self):
          return self.balance
  
      def set_balance(self, balance):
          self.balance = balance
          self.blocks_multiply_const_vxx_0.set_k(1 - self.balance/2)
          self.blocks_multiply_const_vxx_1.set_k(1 + self.balance/2)
  
      def get_ToneLevel(self):
          return self.ToneLevel
  
      def set_ToneLevel(self, ToneLevel):
          self.ToneLevel = ToneLevel
          self.analog_sig_source_x_0.set_amplitude(self.ToneLevel)
  
      def get_ToneFreq(self):
          return self.ToneFreq
  
      def set_ToneFreq(self, ToneFreq):
          self.ToneFreq = ToneFreq
          self.analog_sig_source_x_0.set_frequency(self.ToneFreq)
  
  
  
  
  
  def main(top_block_cls=osc, options=None):
  
      if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
          style = gr.prefs().get_string('qtgui', 'style', 'raster')
          Qt.QApplication.setGraphicsSystem(style)
      qapp = Qt.QApplication(sys.argv)
  
      tb = top_block_cls()
  
      tb.start()
  
      tb.show()
  
      def sig_handler(sig=None, frame=None):
          Qt.QApplication.quit()
  
      signal.signal(signal.SIGINT, sig_handler)
      signal.signal(signal.SIGTERM, sig_handler)
  
      timer = Qt.QTimer()
      timer.start(500)
      timer.timeout.connect(lambda: None)
  
      def quitting():
          tb.stop()
          tb.wait()
  
      qapp.aboutToQuit.connect(quitting)
      qapp.exec_()
  
  if __name__ == '__main__':
      main()
  