1from __future__ import unicode_literals
2#
3# Copyright 2013 Free Software Foundation, Inc.
4#
5# This file is part of GNU Radio.
6#
7# This is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3, or (at your option)
10# any later version.
11#
12# This software is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this software; see the file COPYING.  If not, write to
19# the Free Software Foundation, Inc., 51 Franklin Street,
20# Boston, MA 02110-1301, USA.
21#
22
23###############################################################################
24# Imports
25###############################################################################
26from argparse import ArgumentParser
27from gnuradio.eng_arg import eng_float, intx
28import gui
29import sys
30import os
31from PyQt4 import Qt, QtGui, QtCore, uic
32import PyQt4.Qwt5 as Qwt
33from gnuradio import zeromq
34import signal
35
36class gui(QtGui.QMainWindow):
37    def __init__(self, window_name, options, parent=None):
38        QtGui.QMainWindow.__init__(self, parent)
39
40        # give Ctrl+C back to system
41        signal.signal(signal.SIGINT, signal.SIG_DFL)
42
43        self.gui = uic.loadUi(os.path.join(os.path.dirname(__file__),'main_window.ui'), self)
44
45        self.update_timer = Qt.QTimer()
46
47        # socket addresses
48        rpc_adr_server = "tcp://"+options.servername+":6666"
49        rpc_adr_client = "tcp://"+options.clientname+":6667"
50        probe_adr_server = "tcp://"+options.servername+":5556"
51        probe_adr_client = "tcp://"+options.clientname+":5557"
52
53        # ZeroMQ
54        self.probe_manager = zeromq.probe_manager()
55        self.probe_manager.add_socket(probe_adr_server, 'float32', self.plot_data_server)
56        self.probe_manager.add_socket(probe_adr_client, 'float32', self.plot_data_client)
57
58        self.rpc_mgr_server = zeromq.rpc_manager()
59        self.rpc_mgr_server.set_request_socket(rpc_adr_server)
60        self.rpc_mgr_client = zeromq.rpc_manager()
61        self.rpc_mgr_client.set_request_socket(rpc_adr_client)
62
63        self.gui.setWindowTitle(window_name)
64        self.gui.qwtPlotServer.setTitle("Signal Scope")
65        self.gui.qwtPlotServer.setAxisTitle(Qwt.QwtPlot.xBottom, "Samples")
66        self.gui.qwtPlotServer.setAxisTitle(Qwt.QwtPlot.yLeft, "Amplitude")
67        self.gui.qwtPlotServer.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100)
68        self.gui.qwtPlotServer.setAxisScale(Qwt.QwtPlot.yLeft, -2, 2)
69        self.gui.qwtPlotClient.setTitle("Signal Scope")
70        self.gui.qwtPlotClient.setAxisTitle(Qwt.QwtPlot.xBottom, "Samples")
71        self.gui.qwtPlotClient.setAxisTitle(Qwt.QwtPlot.yLeft, "Amplitude")
72        self.gui.qwtPlotClient.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100)
73        self.gui.qwtPlotClient.setAxisScale(Qwt.QwtPlot.yLeft, -2, 2)
74
75        # Grid
76        pen = Qt.QPen(Qt.Qt.DotLine)
77        pen.setColor(Qt.Qt.black)
78        pen.setWidth(0)
79        grid_server = Qwt.QwtPlotGrid()
80        grid_client = Qwt.QwtPlotGrid()
81        grid_server.setPen(pen)
82        grid_client.setPen(pen)
83        grid_server.attach(self.gui.qwtPlotServer)
84        grid_client.attach(self.gui.qwtPlotClient)
85
86        #Signals
87        self.connect(self.update_timer, QtCore.SIGNAL("timeout()"), self.probe_manager.watcher)
88        self.connect(self.gui.pushButtonRunServer, QtCore.SIGNAL("clicked()"), self.start_fg_server)
89        self.connect(self.gui.pushButtonStopServer, QtCore.SIGNAL("clicked()"), self.stop_fg_server)
90        self.connect(self.gui.pushButtonRunClient, QtCore.SIGNAL("clicked()"), self.start_fg_client)
91        self.connect(self.gui.pushButtonStopClient, QtCore.SIGNAL("clicked()"), self.stop_fg_client)
92        self.connect(self.gui.comboBox, QtCore.SIGNAL("currentIndexChanged(QString)"), self.set_waveform)
93        self.connect(self.gui.spinBox, QtCore.SIGNAL("valueChanged(int)"), self.set_gain)
94        self.shortcut_start = QtGui.QShortcut(Qt.QKeySequence("Ctrl+S"), self.gui)
95        self.shortcut_stop = QtGui.QShortcut(Qt.QKeySequence("Ctrl+C"), self.gui)
96        self.shortcut_exit = QtGui.QShortcut(Qt.QKeySequence("Ctrl+D"), self.gui)
97        self.connect(self.shortcut_exit, QtCore.SIGNAL("activated()"), self.gui.close)
98
99        # start update timer
100        self.update_timer.start(30)
101
102    def start_fg_server(self):
103        self.rpc_mgr_server.request("start_fg")
104
105    def stop_fg_server(self):
106        self.rpc_mgr_server.request("stop_fg")
107
108    def start_fg_client(self):
109        self.rpc_mgr_client.request("start_fg")
110
111    def stop_fg_client(self):
112        self.rpc_mgr_client.request("stop_fg")
113
114    # plot the data from the queues
115    def plot_data(self, plot, samples):
116        self.x = list(range(0,len(samples),1))
117        self.y = samples
118        # clear the previous points from the plot
119        plot.clear()
120        # draw curve with new points and plot
121        curve = Qwt.QwtPlotCurve()
122        curve.setPen(Qt.QPen(Qt.Qt.blue, 2))
123        curve.attach(plot)
124        curve.setData(self.x, self.y)
125        plot.replot()
126
127    def plot_data_server(self, samples):
128        self.plot_data(self.gui.qwtPlotServer, samples)
129
130    def plot_data_client(self, samples):
131        self.plot_data(self.gui.qwtPlotClient, samples)
132
133    def set_waveform(self, waveform_str):
134        self.rpc_mgr_server.request("set_waveform",[str(waveform_str)])
135
136    def set_gain(self, gain):
137        self.rpc_set_gain(gain)
138
139    def rpc_set_gain(self, gain):
140        self.rpc_mgr_server.request("set_k",[gain])
141
142###############################################################################
143# Options Parser
144###############################################################################
145def parse_args():
146    """Options parser."""
147    parser = ArgumentParser()
148    parser.add_argument("-s", "--servername", default="localhost",
149                      help="Server hostname")
150    parser.add_argument("-c", "--clientname", default="localhost",
151                      help="Server hostname")
152    args = parser.parse_args()
153    return args
154
155
156###############################################################################
157# Main
158###############################################################################
159if __name__ == "__main__":
160    args = parse_args()
161    qapp = Qt.QApplication(sys.argv)
162    qapp.main_window = gui("Remote GNU Radio GUI", args)
163    qapp.main_window.show()
164    qapp.exec_()
165
166