#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#
# SPDX-License-Identifier: GPL-3.0
#
# GNU Radio Python Flow Graph
# Title: Just Jammin' Out
# Author: Jack L
# GNU Radio version: 3.10.8.0

from PyQt5 import Qt
from gnuradio import qtgui
from gnuradio import analog
import math
from gnuradio import audio
from gnuradio import blocks
from gnuradio import filter
from gnuradio.filter import firdes
from gnuradio import gr
from gnuradio.fft import window
import sys
import signal
from PyQt5 import Qt
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
from gnuradio.qtgui import Range, RangeWidget
from PyQt5 import QtCore
import sip



class FMmodulator5(gr.top_block, Qt.QWidget):

    def __init__(self):
        gr.top_block.__init__(self, "Just Jammin' Out", catch_exceptions=True)
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Just Jammin' Out")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except BaseException as exc:
            print(f"Qt GUI: Could not set Icon: {str(exc)}", file=sys.stderr)
        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", "FMmodulator5")

        try:
            geometry = self.settings.value("geometry")
            if geometry:
                self.restoreGeometry(geometry)
        except BaseException as exc:
            print(f"Qt GUI: Could not restore geometry: {str(exc)}", file=sys.stderr)

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 48000
        self.Volume = Volume = 1
        self.Sensitivity = Sensitivity = 1
        self.NoiseCutOff = NoiseCutOff = 3000
        self.NoiseAmp = NoiseAmp = 0
        self.Interpolation = Interpolation = 10
        self.CarrierFreq = CarrierFreq = 20000

        ##################################################
        # Blocks
        ##################################################

        self._Volume_range = Range(0, 3, 0.2, 1, 200)
        self._Volume_win = RangeWidget(self._Volume_range, self.set_Volume, "Volume", "counter_slider", float, QtCore.Qt.Horizontal)
        self.top_layout.addWidget(self._Volume_win)
        self._NoiseAmp_range = Range(0, 40, 0.2, 0, 200)
        self._NoiseAmp_win = RangeWidget(self._NoiseAmp_range, self.set_NoiseAmp, "Noise Amplitude", "counter_slider", float, QtCore.Qt.Horizontal)
        self.top_layout.addWidget(self._NoiseAmp_win)
        self.qtgui_waterfall_sink_x_0_1 = qtgui.waterfall_sink_c(
            1024, #size
            window.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            (samp_rate*Interpolation), #bw
            'Modulated Signal', #name
            1, #number of inputs
            None # parent
        )
        self.qtgui_waterfall_sink_x_0_1.set_update_time(0.1)
        self.qtgui_waterfall_sink_x_0_1.enable_grid(True)
        self.qtgui_waterfall_sink_x_0_1.enable_axis_labels(True)



        labels = ['', '', '', '', '',
                  '', '', '', '', '']
        colors = [0, 0, 0, 0, 0,
                  0, 0, 0, 0, 0]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
                  1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_waterfall_sink_x_0_1.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_waterfall_sink_x_0_1.set_line_label(i, labels[i])
            self.qtgui_waterfall_sink_x_0_1.set_color_map(i, colors[i])
            self.qtgui_waterfall_sink_x_0_1.set_line_alpha(i, alphas[i])

        self.qtgui_waterfall_sink_x_0_1.set_intensity_range(-140, 10)

        self._qtgui_waterfall_sink_x_0_1_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0_1.qwidget(), Qt.QWidget)

        self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_0_1_win, 2, 1, 1, 1)
        for r in range(2, 3):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_waterfall_sink_x_0_0 = qtgui.waterfall_sink_f(
            1024, #size
            window.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            (samp_rate*Interpolation), #bw
            'Demodulated Signal', #name
            1, #number of inputs
            None # parent
        )
        self.qtgui_waterfall_sink_x_0_0.set_update_time(0.1)
        self.qtgui_waterfall_sink_x_0_0.enable_grid(True)
        self.qtgui_waterfall_sink_x_0_0.enable_axis_labels(True)


        self.qtgui_waterfall_sink_x_0_0.set_plot_pos_half(not True)

        labels = ['', '', '', '', '',
                  '', '', '', '', '']
        colors = [0, 0, 0, 0, 0,
                  0, 0, 0, 0, 0]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
                  1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_waterfall_sink_x_0_0.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_waterfall_sink_x_0_0.set_line_label(i, labels[i])
            self.qtgui_waterfall_sink_x_0_0.set_color_map(i, colors[i])
            self.qtgui_waterfall_sink_x_0_0.set_line_alpha(i, alphas[i])

        self.qtgui_waterfall_sink_x_0_0.set_intensity_range(-140, 10)

        self._qtgui_waterfall_sink_x_0_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0_0.qwidget(), Qt.QWidget)

        self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_0_0_win, 2, 2, 1, 1)
        for r in range(2, 3):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(2, 3):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_f(
            1024, #size
            window.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            (samp_rate*Interpolation), #bw
            'Message Signal', #name
            1, #number of inputs
            None # parent
        )
        self.qtgui_waterfall_sink_x_0.set_update_time(0.1)
        self.qtgui_waterfall_sink_x_0.enable_grid(True)
        self.qtgui_waterfall_sink_x_0.enable_axis_labels(True)


        self.qtgui_waterfall_sink_x_0.set_plot_pos_half(not True)

        labels = ['', '', '', '', '',
                  '', '', '', '', '']
        colors = [0, 0, 0, 0, 0,
                  0, 0, 0, 0, 0]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
                  1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i])
            self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i])

        self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10)

        self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0.qwidget(), Qt.QWidget)

        self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_0_win, 1, 1, 1, 2)
        for r in range(1, 2):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 3):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.low_pass_filter_0 = filter.fir_filter_ccf(
            1,
            firdes.low_pass(
                1,
                (samp_rate*Interpolation),
                NoiseCutOff,
                200,
                window.WIN_HAMMING,
                6.76))
        self.blocks_wavfile_source_0 = blocks.wavfile_source('C:\\Users\\ISA06016497\\Music\\Guitar_Test_Sound.wav', True)
        self.blocks_multiply_xx_1 = blocks.multiply_vcc(1)
        self.blocks_multiply_xx_0_0 = blocks.multiply_vcc(1)
        self.blocks_multiply_xx_0 = blocks.multiply_vcc(1)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(Volume)
        self.blocks_add_xx_0 = blocks.add_vcc(1)
        self.audio_sink_0 = audio.sink(samp_rate, '', True)
        self.analog_sig_source_x_0_0_0 = analog.sig_source_c((samp_rate*Interpolation), analog.GR_COS_WAVE, CarrierFreq, NoiseAmp, 0, 0)
        self.analog_sig_source_x_0_0 = analog.sig_source_c((samp_rate*Interpolation), analog.GR_COS_WAVE, CarrierFreq, 1, 0, 0)
        self.analog_sig_source_x_0 = analog.sig_source_c((samp_rate*Interpolation), analog.GR_COS_WAVE, CarrierFreq, 1, 0, 0)
        self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf((1/Sensitivity))
        self.analog_phase_modulator_fc_0 = analog.phase_modulator_fc(Sensitivity)
        self.analog_noise_source_x_0 = analog.noise_source_c(analog.GR_GAUSSIAN, 1, 0)


        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.low_pass_filter_0, 0))
        self.connect((self.analog_phase_modulator_fc_0, 0), (self.blocks_multiply_xx_0, 1))
        self.connect((self.analog_quadrature_demod_cf_0, 0), (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 0))
        self.connect((self.analog_sig_source_x_0_0, 0), (self.blocks_multiply_xx_0_0, 0))
        self.connect((self.analog_sig_source_x_0_0_0, 0), (self.blocks_multiply_xx_1, 0))
        self.connect((self.blocks_add_xx_0, 0), (self.blocks_multiply_xx_0_0, 1))
        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_waterfall_sink_x_0_0, 0))
        self.connect((self.blocks_multiply_xx_0, 0), (self.blocks_add_xx_0, 0))
        self.connect((self.blocks_multiply_xx_0, 0), (self.qtgui_waterfall_sink_x_0_1, 0))
        self.connect((self.blocks_multiply_xx_0_0, 0), (self.analog_quadrature_demod_cf_0, 0))
        self.connect((self.blocks_multiply_xx_1, 0), (self.blocks_add_xx_0, 1))
        self.connect((self.blocks_wavfile_source_0, 0), (self.analog_phase_modulator_fc_0, 0))
        self.connect((self.blocks_wavfile_source_0, 0), (self.qtgui_waterfall_sink_x_0, 0))
        self.connect((self.low_pass_filter_0, 0), (self.blocks_multiply_xx_1, 1))


    def closeEvent(self, event):
        self.settings = Qt.QSettings("GNU Radio", "FMmodulator5")
        self.settings.setValue("geometry", self.saveGeometry())
        self.stop()
        self.wait()

        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.Interpolation))
        self.analog_sig_source_x_0_0.set_sampling_freq((self.samp_rate*self.Interpolation))
        self.analog_sig_source_x_0_0_0.set_sampling_freq((self.samp_rate*self.Interpolation))
        self.low_pass_filter_0.set_taps(firdes.low_pass(1, (self.samp_rate*self.Interpolation), self.NoiseCutOff, 200, window.WIN_HAMMING, 6.76))
        self.qtgui_waterfall_sink_x_0.set_frequency_range(0, (self.samp_rate*self.Interpolation))
        self.qtgui_waterfall_sink_x_0_0.set_frequency_range(0, (self.samp_rate*self.Interpolation))
        self.qtgui_waterfall_sink_x_0_1.set_frequency_range(0, (self.samp_rate*self.Interpolation))

    def get_Volume(self):
        return self.Volume

    def set_Volume(self, Volume):
        self.Volume = Volume
        self.blocks_multiply_const_vxx_0.set_k(self.Volume)

    def get_Sensitivity(self):
        return self.Sensitivity

    def set_Sensitivity(self, Sensitivity):
        self.Sensitivity = Sensitivity
        self.analog_phase_modulator_fc_0.set_sensitivity(self.Sensitivity)
        self.analog_quadrature_demod_cf_0.set_gain((1/self.Sensitivity))

    def get_NoiseCutOff(self):
        return self.NoiseCutOff

    def set_NoiseCutOff(self, NoiseCutOff):
        self.NoiseCutOff = NoiseCutOff
        self.low_pass_filter_0.set_taps(firdes.low_pass(1, (self.samp_rate*self.Interpolation), self.NoiseCutOff, 200, window.WIN_HAMMING, 6.76))

    def get_NoiseAmp(self):
        return self.NoiseAmp

    def set_NoiseAmp(self, NoiseAmp):
        self.NoiseAmp = NoiseAmp
        self.analog_sig_source_x_0_0_0.set_amplitude(self.NoiseAmp)

    def get_Interpolation(self):
        return self.Interpolation

    def set_Interpolation(self, Interpolation):
        self.Interpolation = Interpolation
        self.analog_sig_source_x_0.set_sampling_freq((self.samp_rate*self.Interpolation))
        self.analog_sig_source_x_0_0.set_sampling_freq((self.samp_rate*self.Interpolation))
        self.analog_sig_source_x_0_0_0.set_sampling_freq((self.samp_rate*self.Interpolation))
        self.low_pass_filter_0.set_taps(firdes.low_pass(1, (self.samp_rate*self.Interpolation), self.NoiseCutOff, 200, window.WIN_HAMMING, 6.76))
        self.qtgui_waterfall_sink_x_0.set_frequency_range(0, (self.samp_rate*self.Interpolation))
        self.qtgui_waterfall_sink_x_0_0.set_frequency_range(0, (self.samp_rate*self.Interpolation))
        self.qtgui_waterfall_sink_x_0_1.set_frequency_range(0, (self.samp_rate*self.Interpolation))

    def get_CarrierFreq(self):
        return self.CarrierFreq

    def set_CarrierFreq(self, CarrierFreq):
        self.CarrierFreq = CarrierFreq
        self.analog_sig_source_x_0.set_frequency(self.CarrierFreq)
        self.analog_sig_source_x_0_0.set_frequency(self.CarrierFreq)
        self.analog_sig_source_x_0_0_0.set_frequency(self.CarrierFreq)




def main(top_block_cls=FMmodulator5, options=None):

    qapp = Qt.QApplication(sys.argv)

    tb = top_block_cls()

    tb.start()

    tb.show()

    def sig_handler(sig=None, frame=None):
        tb.stop()
        tb.wait()

        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)

    qapp.exec_()

if __name__ == '__main__':
    main()
