diff options
Diffstat (limited to 'gnuradio-core/src/python')
47 files changed, 0 insertions, 7822 deletions
diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py deleted file mode 100644 index cf58a97637..0000000000 --- a/gnuradio-core/src/python/build_utils.py +++ /dev/null @@ -1,226 +0,0 @@ -# -# Copyright 2004,2009,2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -"""Misc utilities used at build time -""" - -import re, os, os.path -from build_utils_codes import * - - -# set srcdir to the directory that contains Makefile.am -try: - srcdir = os.environ['srcdir'] -except KeyError, e: - srcdir = "." -srcdir = srcdir + '/' - -# set do_makefile to either true or false dependeing on the environment -try: - if os.environ['do_makefile'] == '0': - do_makefile = False - else: - do_makefile = True -except KeyError, e: - do_makefile = False - -# set do_sources to either true or false dependeing on the environment -try: - if os.environ['do_sources'] == '0': - do_sources = False - else: - do_sources = True -except KeyError, e: - do_sources = True - -name_dict = {} - -def log_output_name (name): - (base, ext) = os.path.splitext (name) - ext = ext[1:] # drop the leading '.' - - entry = name_dict.setdefault (ext, []) - entry.append (name) - -def open_and_log_name (name, dir): - global do_sources - if do_sources: - f = open (name, dir) - else: - f = None - log_output_name (name) - return f - -def expand_template (d, template_filename, extra = ""): - '''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file - ''' - global do_sources - output_extension = extract_extension (template_filename) - template = open_src (template_filename, 'r') - output_name = d['NAME'] + extra + '.' + output_extension - log_output_name (output_name) - if do_sources: - output = open (output_name, 'w') - do_substitution (d, template, output) - output.close () - template.close () - -def output_glue (dirname): - output_makefile_fragment () - output_ifile_include (dirname) - -def output_makefile_fragment (): - global do_makefile - if not do_makefile: - return -# overwrite the source, which must be writable; this should have been -# checked for beforehand in the top-level Makefile.gen.gen . - f = open (os.path.join (os.environ.get('gendir', os.environ.get('srcdir', '.')), 'Makefile.gen'), 'w') - f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n') - output_subfrag (f, 'h') - output_subfrag (f, 'i') - output_subfrag (f, 'cc') - f.close () - -def output_ifile_include (dirname): - global do_sources - if do_sources: - f = open ('%s_generated.i' % (dirname,), 'w') - f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n') - files = name_dict.setdefault ('i', []) - files.sort () - f.write ('%{\n') - for file in files: - f.write ('#include <%s>\n' % (file[0:-1] + 'h',)) - f.write ('%}\n\n') - for file in files: - f.write ('%%include <%s>\n' % (file,)) - -def output_subfrag (f, ext): - files = name_dict.setdefault (ext, []) - files.sort () - f.write ("GENERATED_%s =" % (ext.upper ())) - for file in files: - f.write (" \\\n\t%s" % (file,)) - f.write ("\n\n") - -def extract_extension (template_name): - # template name is something like: GrFIRfilterXXX.h.t - # we return everything between the penultimate . and .t - mo = re.search (r'\.([a-z]+)\.t$', template_name) - if not mo: - raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,) - return mo.group (1) - -def open_src (name, mode): - global srcdir - return open (os.path.join (srcdir, name), mode) - -def do_substitution (d, in_file, out_file): - def repl (match_obj): - key = match_obj.group (1) - # print key - return d[key] - - inp = in_file.read () - out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp) - out_file.write (out) - - - -copyright = '''/* -*- c++ -*- */ -/* - * Copyright 2003,2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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; either version 3, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -''' - -def is_complex (code3): - if i_code (code3) == 'c' or o_code (code3) == 'c': - return '1' - else: - return '0' - - -def standard_dict (name, code3, package='gr'): - d = {} - d['NAME'] = name - d['NAME_IMPL'] = name+'_impl' - d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) - d['GUARD_NAME_IMPL'] = 'INCLUDED_%s_%s_IMPL_H' % (package.upper(), name.upper()) - d['BASE_NAME'] = re.sub ('^' + package + '_', '', name) - d['SPTR_NAME'] = '%s_sptr' % name - d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' - d['COPYRIGHT'] = copyright - d['TYPE'] = i_type (code3) - d['I_TYPE'] = i_type (code3) - d['O_TYPE'] = o_type (code3) - d['TAP_TYPE'] = tap_type (code3) - d['IS_COMPLEX'] = is_complex (code3) - return d - - -def standard_dict2 (name, code3, package): - d = {} - d['NAME'] = name - d['BASE_NAME'] = name - d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) - d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' - d['COPYRIGHT'] = copyright - d['TYPE'] = i_type (code3) - d['I_TYPE'] = i_type (code3) - d['O_TYPE'] = o_type (code3) - d['TAP_TYPE'] = tap_type (code3) - d['IS_COMPLEX'] = is_complex (code3) - return d - -def standard_impl_dict2 (name, code3, package): - d = {} - d['NAME'] = name - d['IMPL_NAME'] = name - d['BASE_NAME'] = name.rstrip("impl").rstrip("_") - d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) - d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' - d['COPYRIGHT'] = copyright - d['FIR_TYPE'] = "fir_filter_" + code3 - d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c' - d['TYPE'] = i_type (code3) - d['I_TYPE'] = i_type (code3) - d['O_TYPE'] = o_type (code3) - d['TAP_TYPE'] = tap_type (code3) - d['IS_COMPLEX'] = is_complex (code3) - return d diff --git a/gnuradio-core/src/python/build_utils_codes.py b/gnuradio-core/src/python/build_utils_codes.py deleted file mode 100644 index 9ea96baae4..0000000000 --- a/gnuradio-core/src/python/build_utils_codes.py +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2004 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -def i_code (code3): - return code3[0] - -def o_code (code3): - if len (code3) >= 2: - return code3[1] - else: - return code3[0] - -def tap_code (code3): - if len (code3) >= 3: - return code3[2] - else: - return code3[0] - -def i_type (code3): - return char_to_type[i_code (code3)] - -def o_type (code3): - return char_to_type[o_code (code3)] - -def tap_type (code3): - return char_to_type[tap_code (code3)] - - -char_to_type = {} -char_to_type['s'] = 'short' -char_to_type['i'] = 'int' -char_to_type['f'] = 'float' -char_to_type['c'] = 'gr_complex' -char_to_type['b'] = 'unsigned char' diff --git a/gnuradio-core/src/python/gnuradio/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/CMakeLists.txt deleted file mode 100644 index 9b75f20f33..0000000000 --- a/gnuradio-core/src/python/gnuradio/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -include(GrPython) - -add_subdirectory(gr) -add_subdirectory(gru) -add_subdirectory(gruimpl) - -if(ENABLE_GR_CTRLPORT) -add_subdirectory(ctrlport) -endif(ENABLE_GR_CTRLPORT) - -GR_PYTHON_INSTALL(FILES - __init__.py - eng_notation.py - eng_option.py - gr_unittest.py - gr_xmlrunner.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio - COMPONENT "core_python" -) diff --git a/gnuradio-core/src/python/gnuradio/__init__.py b/gnuradio-core/src/python/gnuradio/__init__.py deleted file mode 100644 index d55dac79db..0000000000 --- a/gnuradio-core/src/python/gnuradio/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software radios. It can be used with readily-available low-cost external RF hardware to create software-defined radios, or without hardware in a simulation-like environment. It is widely used in hobbyist, academic and commercial environments to support both wireless communications research and real-world radio systems. - -GNU Radio applications are primarily written using the Python programming language, while the supplied performance-critical signal-processing path is implemented in C++ using processor floating-point extensions, where available. Thus, the developer is able to implement real-time, high-throughput radio systems in a simple-to-use, rapid-application-development environment. - -While not primarily a simulation tool, GNU Radio does support development of signal processing algorithms using pre-recorded or generated data, avoiding the need for actual RF hardware. - -GNU Radio is licensed under the GNU General Public License (GPL) version 3. All of the code is copyright of the Free Software Foundation. -""" - -# This file makes gnuradio a package -# The docstring will be associated with the top level of the package. diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt deleted file mode 100644 index 994e3a48cf..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -######################################################################## -include(GrPython) - -EXECUTE_PROCESS( - COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/runtime - --output-dir=${CMAKE_BINARY_DIR}/gnuradio-core/src/python - ${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/runtime/gnuradio.ice -) - -EXECUTE_PROCESS( - COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/runtime - --output-dir=${CMAKE_BINARY_DIR}/gnuradio-core/src/python - ${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/runtime/frontend.ice -) - -GR_PYTHON_INSTALL( - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py - ${CMAKE_CURRENT_SOURCE_DIR}/IceRadioClient.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/ - COMPONENT "core_python" -) - -# We don't want to install these in the root Python directory, but we -# aren't given a choice based on the way slice2py generates the -# information. -GR_PYTHON_INSTALL( - FILES - ${CMAKE_BINARY_DIR}/gnuradio-core/src/python/gnuradio_ice.py - ${CMAKE_BINARY_DIR}/gnuradio-core/src/python/frontend_ice.py - DESTINATION ${GR_PYTHON_DIR} - COMPONENT "core_python" -) - -GR_PYTHON_INSTALL( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/__init__.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio - COMPONENT "core_python" -) - -GR_PYTHON_INSTALL( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/Booter/__init__.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio/Booter - COMPONENT "core_python" -) - -GR_PYTHON_INSTALL( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/Frontend/__init__.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio/Frontend - COMPONENT "core_python" -) - -install( - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/icon.png - DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport - COMPONENT "core_python" -) - -GR_PYTHON_INSTALL( - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/GrDataPlotter.py - ${CMAKE_CURRENT_SOURCE_DIR}/monitor.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/ - COMPONENT "core_python" -) - -GR_PYTHON_INSTALL( - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/gr-ctrlport-monitor - ${CMAKE_CURRENT_SOURCE_DIR}/gr-ctrlport-curses - DESTINATION ${GR_RUNTIME_DIR} - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - COMPONENT "core_python" -) - -######################################################################## -# Handle the unit tests -######################################################################## -if(ENABLE_GR_CTRLPORT) - if(ENABLE_TESTING) - include(GrTest) - file(GLOB py_qa_test_files "qa_*.py") - foreach(py_qa_test_file ${py_qa_test_files}) - get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - set(GR_TEST_TARGET_DEPS gruel gnuradio-core) - GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file}) - endforeach(py_qa_test_file) - endif(ENABLE_TESTING) -endif(ENABLE_GR_CTRLPORT) diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py deleted file mode 100644 index 8597ca6497..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py +++ /dev/null @@ -1,428 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012,2013 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr -from gnuradio import blocks -from gnuradio import filter -import sys, time - -try: - from gnuradio import qtgui - from PyQt4 import QtGui, QtCore - import sip -except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." - sys.exit(1) - -class GrDataPlotParent(gr.top_block, QtGui.QWidget): - # Setup signals - plotupdated = QtCore.pyqtSignal(QtGui.QWidget) - - def __init__(self, name, rate, pmin=None, pmax=None): - gr.top_block.__init__(self) - QtGui.QWidget.__init__(self, None) - - self._name = name - self._npts = 500 - self._rate = rate - self.knobnames = [name,] - - self.layout = QtGui.QVBoxLayout() - self.setLayout(self.layout) - - self.setAcceptDrops(True) - - def _setup(self, nconnections): - self.stop() - self.wait() - - if(self.layout.count() > 0): - # Remove and disconnect. Making sure no references to snk - # remain so that the plot gets deleted. - self.layout.removeWidget(self.py_window) - self.disconnect(self.thr, (self.snk, 0)) - self.disconnect(self.src[0], self.thr) - for n in xrange(1, self._ncons): - self.disconnect(self.src[n], (self.snk,n)) - - self._ncons = nconnections - self._data_len = self._ncons*[0,] - - self.thr = blocks.throttle(self._datasize, self._rate) - self.snk = self.get_qtsink() - - self.connect(self.thr, (self.snk, 0)) - - self._last_data = [] - self.src = [] - for n in xrange(self._ncons): - self.set_line_label(n, self.knobnames[n]) - - self._last_data.append(int(self._npts)*[0,]) - self.src.append(self.get_vecsource()) - - if(n == 0): - self.connect(self.src[n], self.thr) - else: - self.connect(self.src[n], (self.snk,n)) - - self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget) - - self.layout.addWidget(self.py_window) - - def __del__(self): - pass - - def close(self): - self.snk.close() - - def qwidget(self): - return self.py_window - - def name(self): - return self._name - - def semilogy(self, en=True): - self.snk.enable_semilogy(en) - - def dragEnterEvent(self, e): - e.acceptProposedAction() - - def dropEvent(self, e): - if(e.mimeData().hasFormat("text/plain")): - data = str(e.mimeData().text()) - - #"PlotData:{0}:{1}".format(tag, iscomplex) - datalst = data.split(":::") - tag = datalst[0] - name = datalst[1] - cpx = datalst[2] != "0" - - if(tag == "PlotData" and cpx == self._iscomplex): - self.knobnames.append(name) - - # create a new qwidget plot with the new data stream. - self._setup(len(self.knobnames)) - - # emit that this plot has been updated with a new qwidget. - self.plotupdated.emit(self) - - e.acceptProposedAction() - - def data_to_complex(self, data): - if(self._iscomplex): - data_r = data[0::2] - data_i = data[1::2] - data = [complex(r,i) for r,i in zip(data_r, data_i)] - return data - - def update(self, data): - # Ask GUI if there has been a change in nsamps - npts = self.get_npts() - if(self._npts != npts): - - # Adjust buffers to accomodate new settings - for n in xrange(self._ncons): - if(npts < self._npts): - if(self._data_len[n] < npts): - self._last_data[n] = self._last_data[n][0:npts] - else: - self._last_data[n] = self._last_data[n][self._data_len[n]-npts:self._data_len[n]] - self._data_len[n] = npts - else: - self._last_data[n] += (npts - self._npts)*[0,] - self._npts = npts - self.snk.reset() - - if(self._stripchart): - # Update the plot data depending on type - for n in xrange(self._ncons): - if(type(data[n]) == list): - data[n] = self.data_to_complex(data[n]) - if(len(data[n]) > self._npts): - self.src[n].set_data(data[n]) - self._last_data[n] = data[n][-self._npts:] - else: - newdata = self._last_data[n][-(self._npts-len(data)):] - newdata += data[n] - self.src[n].set_data(newdata) - self._last_data[n] = newdata - - else: # single value update - if(self._iscomplex): - data[n] = complex(data[n][0], data[n][1]) - if(self._data_len[n] < self._npts): - self._last_data[n][self._data_len[n]] = data[n] - self._data_len[n] += 1 - else: - self._last_data[n] = self._last_data[n][1:] - self._last_data[n].append(data[n]) - self.src[n].set_data(self._last_data[n]) - else: - for n in xrange(self._ncons): - if(type(data[n]) != list): - data[n] = [data[n],] - data[n] = self.data_to_complex(data[n]) - self.src[n].set_data(data[n]) - - - -class GrDataPlotterC(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._stripchart = stripchart - self._datasize = gr.sizeof_gr_complex - self._iscomplex = True - - self._setup(1) - - def stem(self, en=True): - self.snk.enable_stem_plot(en) - - def get_qtsink(self): - snk = qtgui.time_sink_c(self._npts, 1.0, - self._name, self._ncons) - snk.enable_autoscale(True) - return snk - - def get_vecsource(self): - return blocks.vector_source_c([]) - - def get_npts(self): - self._npts = self.snk.nsamps() - return self._npts - - def set_line_label(self, n, name): - self.snk.set_line_label(2*n+0, "Re{" + self.knobnames[n] + "}") - self.snk.set_line_label(2*n+1, "Im{" + self.knobnames[n] + "}") - - -class GrDataPlotterF(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._stripchart = stripchart - self._datasize = gr.sizeof_float - self._iscomplex = False - - self._setup(1) - - def stem(self, en=True): - self.snk.enable_stem_plot(en) - - def get_qtsink(self): - snk = qtgui.time_sink_f(self._npts, 1.0, - self._name, self._ncons) - snk.enable_autoscale(True) - return snk - - def get_vecsource(self): - return blocks.vector_source_f([]) - - def get_npts(self): - self._npts = self.snk.nsamps() - return self._npts - - def set_line_label(self, n, name): - self.snk.set_line_label(n, self.knobnames[n]) - - -class GrDataPlotterConst(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._datasize = gr.sizeof_gr_complex - self._stripchart = False - self._iscomplex = True - - self._setup(1) - - def get_qtsink(self): - snk = qtgui.const_sink_c(self._npts, - self._name, - self._ncons) - snk.enable_autoscale(True) - return snk - - def get_vecsource(self): - return blocks.vector_source_c([]) - - def get_npts(self): - self._npts = self.snk.nsamps() - return self._npts - - def scatter(self, en=True): - if(en): - self.snk.set_line_style(0, 0) - else: - self.snk.set_line_style(0, 1) - - def set_line_label(self, n, name): - self.snk.set_line_label(n, self.knobnames[n]) - - -class GrDataPlotterPsdC(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._datasize = gr.sizeof_gr_complex - self._stripchart = True - self._iscomplex = True - - self._npts = 2048 - self._wintype = filter.firdes.WIN_BLACKMAN_hARRIS - self._fc = 0 - - self._setup(1) - - def get_qtsink(self): - snk = qtgui.freq_sink_c(self._npts, self._wintype, - self._fc, 1.0, - self._name, - self._ncons) - snk.enable_autoscale(True) - return snk - - def get_vecsource(self): - return blocks.vector_source_c([]) - - def get_npts(self): - self._npts = self.snk.fft_size() - return self._npts - - def set_line_label(self, n, name): - self.snk.set_line_label(n, self.knobnames[n]) - - -class GrDataPlotterPsdF(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._datasize = gr.sizeof_float - self._stripchart = True - self._iscomplex = False - - self._npts = 2048 - self._wintype = filter.firdes.WIN_BLACKMAN_hARRIS - self._fc = 0 - - self._setup(1) - - def get_qtsink(self): - snk = qtgui.freq_sink_f(self._npts, self._wintype, - self._fc, 1.0, - self._name, - self._ncons) - snk.enable_autoscale(True) - return snk - - def get_vecsource(self): - return blocks.vector_source_f([]) - - def get_npts(self): - self._npts = self.snk.fft_size() - return self._npts - - def set_line_label(self, n, name): - self.snk.set_line_label(n, self.knobnames[n]) - - -class GrTimeRasterF(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._npts = 10 - self._rows = 40 - - self._datasize = gr.sizeof_float - self._stripchart = False - self._iscomplex = False - - self._setup(1) - - def get_qtsink(self): - snk = qtgui.time_raster_sink_f(1.0, self._npts, self._rows, - [], [], self._name, - self._ncons) - return snk - - def get_vecsource(self): - return blocks.vector_source_f([]) - - def get_npts(self): - self._npts = self.snk.num_cols() - return self._npts - - def set_line_label(self, n, name): - self.snk.set_line_label(n, self.knobnames[n]) - -class GrTimeRasterB(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None): - GrDataPlotParent.__init__(self, name, rate, pmin, pmax) - - self._npts = 10 - self._rows = 40 - - self._datasize = gr.sizeof_char - self._stripchart = False - self._iscomplex = False - - self._setup(1) - - def get_qtsink(self): - snk = qtgui.time_raster_sink_b(1.0, self._npts, self._rows, - [], [], self._name, - self._ncons) - return snk - - def get_vecsource(self): - return blocks.vector_source_b([]) - - def get_npts(self): - self._npts = self.snk.num_cols() - return self._npts - - def set_line_label(self, n, name): - self.snk.set_line_label(n, self.knobnames[n]) - - -class GrDataPlotterValueTable: - def __init__(self, uid, parent, x, y, xsize, ysize, - headers=['Statistic Key ( Source Block :: Stat Name ) ', - 'Curent Value', 'Units', 'Description']): - # must encapsulate, cuz Qt's bases are not classes - self.uid = uid - self.treeWidget = QtGui.QTreeWidget(parent) - self.treeWidget.setColumnCount(len(headers)) - self.treeWidget.setGeometry(x,y,xsize,ysize) - self.treeWidget.setHeaderLabels(headers) - self.treeWidget.resizeColumnToContents(0) - - def updateItems(self, knobs, knobprops): - items = []; - self.treeWidget.clear() - for k, v in knobs.iteritems(): - items.append(QtGui.QTreeWidgetItem([str(k), str(v.value), - knobprops[k].units, - knobprops[k].description])) - self.treeWidget.insertTopLevelItems(0, items) diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/IceRadioClient.py b/gnuradio-core/src/python/gnuradio/ctrlport/IceRadioClient.py deleted file mode 100644 index 0964b5a4ba..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/IceRadioClient.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import Ice, Glacier2 -from PyQt4 import QtGui, QtCore -import sys, time, Ice -from gnuradio import gr -from gnuradio.ctrlport import GNURadio - -class IceRadioClient(Ice.Application): - def __init__(self, parentClass): - self.parentClass = parentClass - - def getRadio(self, host, port): - radiostr = "gnuradio -t:tcp -h " + host + " -p " + port + " -t 3000" - base = self.communicator().stringToProxy(radiostr).ice_twoway() - radio = GNURadio.ControlPortPrx.checkedCast(base) - - if not radio: - sys.stderr.write("{0} : invalid proxy.\n".format(args[0])) - return None - - return radio - - def run(self,args): - if len(args) < 2: - print "useage: [glacierinstance glacierhost glacierport] host port" - return - if len(args) == 8: - self.useglacier = True - guser = args[1] - gpass = args[2] - ginst = args[3] - ghost = args[4] - gport = args[5] - host = args[6] - port = args[7] - else: - self.useglacier = False - host = args[1] - port = args[2] - - if self.useglacier: - gstring = ginst + "/router -t:tcp -h " + ghost + " -p " + gport - print "GLACIER: {0}".format(gstring) - - setrouter = Glacier2.RouterPrx.checkedCast(self.communicator().stringToProxy(gstring)) - self.communicator().setDefaultRouter(setrouter) - defaultRouter = self.communicator().getDefaultRouter() - #defaultRouter = self.communicator().stringToProxy(gstring) - if not defaultRouter: - print self.appName() + ": no default router set" - return 1 - else: - print str(defaultRouter) - router = Glacier2.RouterPrx.checkedCast(defaultRouter) - if not router: - print self.appName() + ": configured router is not a Glacier2 router" - return 1 - - while True: - print "This demo accepts any user-id / password combination." - if not guser == '' and not gpass == '': - id = guser - pw = gpass - else: - id = raw_input("user id: ") - pw = raw_input("password: ") - - try: - router.createSession(id, pw) - break - except Glacier2.PermissionDeniedException, ex: - print "permission denied:\n" + ex.reason - - radio = self.getRadio(host, port) - if(radio is None): - return 1 - - app = QtGui.QApplication(sys.argv) - ex = self.parentClass(radio, port, self) - ex.show(); - app.exec_() diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/__init__.py b/gnuradio-core/src/python/gnuradio/ctrlport/__init__.py deleted file mode 100644 index 031c3b424e..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -# The presence of this file turns this directory into a Python package - -import Ice, IcePy - -# import swig generated symbols into the ctrlport namespace -#from ctrlport_swig import * -from monitor import * - -# import any pure python here -#import GNURadio diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-curses b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-curses deleted file mode 100755 index 1bee3b1a1e..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-curses +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import threading -import curses -import os, sys, time -from optparse import OptionParser - -import Ice -from gnuradio.ctrlport import GNURadio - -ENTER = chr(10) -UP_ARROW = chr(65) -DOWN_ARROW = chr(66) - -class modem_monitor(threading.Thread): - def __init__(self, cb_live, cb_exit, interface): - threading.Thread.__init__(self) - self.cb_live = cb_live - self.cb_exit = cb_exit - - self.running = True - - def __del__(self): - rx.close() - - def run(self): - while self.running: - time.sleep(0.5) - - def shutdown(self): - self.running = False - self.rx.close() - - def cb(self,contents): - (op, sep, payload) = contents.partition(":") - if(op == "live"): - print "live" - self.cb_live(payload) - elif(op == "exit"): - self.cb_exit(payload) - else: - print "unknown op arrived! garbage on multicast adx?" - -class modem_window(threading.Thread): - def __init__(self, locator): - threading.Thread.__init__(self) - self.locator = locator - - # curses init - self.win = curses.newwin(30,100,4,4) - - # Ice/GRCP init - self.comm = Ice.initialize() - proxy = self.comm.stringToProxy(locator) - self.radio = GNURadio.ControlPortPrx.checkedCast(proxy) - self.updateKnobs() - - # GUI init - self.running = True - self.ssel = 0 - self.start() - #self.updateGUI() - - # input loop - while(self.running): - self.getInput() - - # wait for update thread exit - self.join() - - def updateKnobs(self): - self.knobs = self.radio.get([]) - - def getInput(self): - a = self.win.getch() - if(a <= 256): - a = chr(a) - if(a == 'q'): - self.running = False - elif(a == UP_ARROW): - self.ssel = max(self.ssel-1, 0) - self.updateGUI() - elif(a == DOWN_ARROW): - self.ssel = max(min(self.ssel+1, len(self.knobs.keys())-1),0) - self.updateGUI() - self.updateGUI() - - def updateGUI(self): - self.win.clear() - self.win.border(0) - self.win.addstr(1, 2, "Modem Statistics :: %s"%(self.locator)) - self.win.addstr(2, 2, "---------------------------------------------------") - - maxnb = 0 - maxk = 0 - for k in self.knobs.keys(): - (nb,k) = k.split("::", 2) - maxnb = max(maxnb,len(nb)) - maxk = max(maxk,len(k)) - - offset = 3 - keys = self.knobs.keys() - keys.sort() - for k in keys: - (nb,sk) = k.split("::", 2) - v = self.knobs[k].value - sv = str(v) - if(len(sv) > 20): - sv = sv[0:20] - props = 0 - if(self.ssel == offset-3): - props = props | curses.A_REVERSE - self.win.addstr(offset, 2, "%s %s %s" % \ - (nb.rjust(maxnb," "), sk.ljust(maxk," "), sv),props) - offset = offset + 1 - self.win.refresh() - - def run(self): - while(self.running): - self.updateKnobs() - self.updateGUI() - time.sleep(1) - -class monitor_gui: - def __init__(self, interfaces, options): - - locator = None - - # Extract options into a locator - if(options.host and options.port): - locator = "{0} -t:{1} -h {2} -p {3}".format( - options.app, options.protocol, - options.host, options.port) - - # Set up GUI - self.locators = {} - - self.mode = 0 # modem index screen (modal keyboard input) - self.lsel = 0 # selected locator - self.scr = curses.initscr() - self.updateGUI() - - # Kick off initial monitors - self.monitors = [] - for i in interfaces: - self.monitors.append( modem_monitor(self.addModem, self.delModem, i) ) - self.monitors[-1].start() - - if not ((locator == None) or (locator == "")): - self.addModem(locator) - - # wait for user input - while(True): - self.getInput() - - def addModem(self, locator): - if(not self.locators.has_key(locator)): - self.locators[locator] = {} - self.locators[locator]["update_time"] = time.time() - self.locators[locator]["status"] = "live" - - self.updateGUI(); - - def delModem(self, locator): - #if(self.locators.has_key(locator)): - if(not self.locators.has_key(locator)): - self.locators[locator] = {} - self.locators[locator]["update_time"] = time.time() - self.locators[locator]["status"] = "exit" - - self.updateGUI() - - def updateGUI(self): - if(self.mode == 0): #redraw locators - self.scr.clear() - self.scr.border(0) - self.scr.addstr(1, 2, " GRCP-Curses Modem Monitor :: (A)dd (R)efresh, (Q)uit, ...") - for i in range(len(self.locators.keys())): - locator = self.locators.keys()[i] - lhash = self.locators[locator] - #self.scr.addstr(3+i, 5, locator + str(lhash)) - props = 0 - if(self.lsel == i): - props = props | curses.A_REVERSE - self.scr.addstr(3+i, 5, locator + str(lhash), props) - self.scr.refresh() - - def connectGUI(self): - self.scr.clear() - self.scr.addstr(1, 1, "Connect to radio:") - locator = self.scr.getstr(200) - self.addModem(locator) - self.updateGUI() - - def getInput(self): - a = self.scr.getch() - self.scr.addstr(20, 2, "got key (%d) " % (int(a))) - if(a <= 256): - a = chr(a) - if(a =='r'): - self.updateGUI() - elif(a == 'q'): - self.shutdown() - elif(a == 'a'): - self.connectGUI() - elif(a == UP_ARROW): - self.lsel = max(self.lsel-1, 0) - self.updateGUI() - elif(a == DOWN_ARROW): - self.lsel = max(min(self.lsel+1, len(self.locators.keys())-1),0) - self.updateGUI() - elif(a == ENTER): - try: - locator = self.locators.keys()[self.lsel] - self.mode = 1 - mwin = modem_window(locator) - self.mode = 0 - # pop up a new modem display ... - self.updateGUI() - except: - pass - - def shutdown(self): - curses.endwin() - os._exit(0) - -if __name__ == "__main__": - parser = OptionParser() - parser.add_option("-H", "--host", type="string", - help="Hostname of ControlPort server.") - parser.add_option("-p", "--port", type="int", - help="Port number of host's ControlPort endpoint.") - parser.add_option("-i", "--interfaces", type="string", - action="append", default=["lo"], - help="Interfaces to use. [default=%default]") - parser.add_option("-P", "--protocol", type="string", default="tcp", - help="Type of protocol to use (usually tcp). [default=%default]") - parser.add_option("-a", "--app", type="string", default="gnuradio", - help="Name of application [default=%default]") - (options, args) = parser.parse_args() - - if((options.host == None) ^ (options.port == None)): - print "Please set both a hostname and a port number.\n" - parser.print_help() - sys.exit(1) - - mg = monitor_gui(options.interfaces, options) - diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor deleted file mode 100755 index e71cd92ab7..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor +++ /dev/null @@ -1,721 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012,2013 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, ctrlport - -from PyQt4 import QtCore,Qt -import PyQt4.QtGui as QtGui -import os, sys, time - -import Ice -from gnuradio.ctrlport.IceRadioClient import * -from gnuradio.ctrlport.GrDataPlotter import * -from gnuradio.ctrlport import GNURadio - -class RateDialog(QtGui.QDialog): - def __init__(self, delay, parent=None): - super(RateDialog, self).__init__(parent) - self.gridLayout = QtGui.QGridLayout(self) - self.setWindowTitle("Update Delay (ms)"); - self.delay = QtGui.QLineEdit(self); - self.delay.setText(str(delay)); - self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) - self.gridLayout.addWidget(self.delay); - self.gridLayout.addWidget(self.buttonBox); - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) - def accept(self): - self.done(1); - def reject(self): - self.done(0); - -class MAINWindow(QtGui.QMainWindow): - def minimumSizeHint(self): - return Qtgui.QSize(800,600) - - def __init__(self, radio, port, interface): - - super(MAINWindow, self).__init__() - self.updateRate = 1000; - self.conns = [] - self.plots = [] - self.knobprops = [] - self.interface = interface - - self.mdiArea = QtGui.QMdiArea() - self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.setCentralWidget(self.mdiArea) - - self.mdiArea.subWindowActivated.connect(self.updateMenus) - self.windowMapper = QtCore.QSignalMapper(self) - self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow) - - self.createActions() - self.createMenus() - self.createToolBars() - self.createStatusBar() - self.updateMenus() - - self.setWindowTitle("GNU Radio Control Port Monitor") - self.setUnifiedTitleAndToolBarOnMac(True) - - self.newCon(radio, port) - icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" ) - self.setWindowIcon(icon) - - # Locally turn off ControlPort export from GR. This prevents - # our GR-based plotters from launching their own ControlPort - # instance (and possibly causing a port collision if one has - # been specified). - os.environ['GR_CONF_CONTROLPORT_ON'] = 'False' - - def setUpdateRate(self,nur): - self.updateRate = int(nur); - for c in self.conns: - c.updateRate = self.updateRate; - c.timer.setInterval(self.updateRate); - - def newCon(self, radio=None, port=None): - child = MForm(radio, port, len(self.conns), self.updateRate, self) - if(child.radio is not None): - child.setWindowTitle(str(child.radio)) - self.mdiArea.addSubWindow(child) - child.showMaximized() - self.conns.append(child) - self.plots.append([]) - - def propertiesMenu(self, key, radio, uid): - r = str(radio).split(" ") - title = "{0}:{1}".format(r[3], r[5]) - - props = radio.properties([key]) - pmin = props[key].min.value - pmax = props[key].max.value - if pmin == []: - pmin = None - else: - pmin = 1.1*pmin - if pmax == []: - pmax = None - else: - pmax = 1.1*pmax - - # Use display option mask of item to set up available plot - # types and default options. - disp = self.knobprops[uid][key].display - cplx = disp & gr.DISPOPTCPLX | disp & gr.DISPXY - strip = disp & gr.DISPOPTSTRIP - stem = disp & gr.DISPOPTSTEM - log = disp & gr.DISPOPTLOG - scatter = disp & gr.DISPOPTSCATTER - - def newUpdaterProxy(): - self.newUpdater(key, radio) - - def newPlotterFProxy(): - self.newPlotF(key, uid, title, pmin, pmax, - log, strip, stem) - - def newPlotterCProxy(): - self.newPlotC(key, uid, title, pmin, pmax, - log, strip, stem) - - def newPlotterConstProxy(): - self.newPlotConst(key, uid, title, pmin, pmax, scatter) - - def newPlotterPsdFProxy(): - self.newPlotPsdF(key, uid, title) - - def newPlotterPsdCProxy(): - self.newPlotPsdC(key, uid, title) - - def newPlotterRasterFProxy(): - self.newPlotRasterF(key, uid, title, pmin, pmax) - - def newPlotterRasterBProxy(): - self.newPlotRasterB(key, uid, title, pmin, pmax) - - menu = QtGui.QMenu(self) - menu.setTitle("Item Actions") - menu.setTearOffEnabled(False) - - # object properties - menu.addAction("Properties", newUpdaterProxy) - - # displays available - if(cplx == 0): - menu.addAction("Plot Time", newPlotterFProxy) - menu.addAction("Plot PSD", newPlotterPsdFProxy) - menu.addAction("Plot Raster (real)", newPlotterRasterFProxy) - #menu.addAction("Plot Raster (bits)", newPlotterRasterBProxy) - else: - menu.addAction("Plot Time", newPlotterCProxy) - menu.addAction("Plot PSD", newPlotterPsdCProxy) - menu.addAction("Plot Constellation", newPlotterConstProxy) - - menu.popup(QtGui.QCursor.pos()) - - def newUpdater(self, key, radio): - updater = UpdaterWindow(key, radio, None) - updater.setWindowTitle("Updater: " + key) - updater.setModal(False) - updater.exec_() - - def newSub(self, e): - tag = str(e.text(0)) - tree = e.treeWidget().parent() - uid = tree.uid - knobprop = self.knobprops[uid][tag] - - r = str(tree.radio).split(" ") - title = "{0}:{1}".format(r[3], r[5]) - pmin = knobprop.min.value - pmax = knobprop.max.value - if pmin == []: - pmin = None - else: - pmin = 1.1*pmin - if pmax == []: - pmax = None - else: - pmax = 1.1*pmax - - disp = knobprop.display - if(disp & gr.DISPTIME): - strip = disp & gr.DISPOPTSTRIP - stem = disp & gr.DISPOPTSTEM - log = disp & gr.DISPOPTLOG - if(disp & gr.DISPOPTCPLX == 0): - self.newPlotF(tag, uid, title, pmin, pmax, - log, strip, stem) - else: - self.newPlotC(tag, uid, title, pmin, pmax, - log, strip, stem) - - elif(disp & gr.DISPXY): - scatter = disp & gr.DISPOPTSCATTER - self.newPlotConst(tag, uid, title, pmin, pmax, scatter) - - elif(disp & gr.DISPPSD): - if(disp & gr.DISPOPTCPLX == 0): - self.newPlotPsdF(tag, uid, title) - else: - self.newPlotPsdC(tag, uid, title) - - def startDrag(self, e): - drag = QtGui.QDrag(self) - mime_data = QtCore.QMimeData() - - tag = str(e.text(0)) - tree = e.treeWidget().parent() - knobprop = self.knobprops[tree.uid][tag] - disp = knobprop.display - iscomplex = (disp & gr.DISPOPTCPLX) or (disp & gr.DISPXY) - - if(disp != gr.DISPNULL): - data = "PlotData:::{0}:::{1}".format(tag, iscomplex) - else: - data = "OtherData:::{0}:::{1}".format(tag, iscomplex) - - mime_data.setText(data) - drag.setMimeData(mime_data) - - drop = drag.start() - - def createPlot(self, plot, uid, title): - plot.start() - self.plots[uid].append(plot) - - self.mdiArea.addSubWindow(plot) - plot.setWindowTitle("{0}: {1}".format(title, plot.name())) - self.connect(plot.qwidget(), - QtCore.SIGNAL('destroyed(QObject*)'), - self.destroyPlot) - - # when the plot is updated via drag-and-drop, we need to be - # notified of the new qwidget that's created so we can - # properly destroy it. - plot.plotupdated.connect(self.plotUpdated) - - plot.show() - - def plotUpdated(self, q): - # the plot has been updated with a new qwidget; make sure this - # gets dies to the destroyPlot function. - for i, plots in enumerate(self.plots): - for p in plots: - if(p == q): - #plots.remove(p) - #plots.append(q) - self.connect(q.qwidget(), - QtCore.SIGNAL('destroyed(QObject*)'), - self.destroyPlot) - break - - def destroyPlot(self, obj): - for plots in self.plots: - for p in plots: - if p.qwidget() == obj: - plots.remove(p) - break - - def newPlotConst(self, tag, uid, title="", pmin=None, pmax=None, - scatter=False): - plot = GrDataPlotterConst(tag, 32e6, pmin, pmax) - plot.scatter(scatter) - self.createPlot(plot, uid, title) - - def newPlotF(self, tag, uid, title="", pmin=None, pmax=None, - logy=False, stripchart=False, stem=False): - plot = GrDataPlotterF(tag, 32e6, pmin, pmax, stripchart) - plot.semilogy(logy) - plot.stem(stem) - self.createPlot(plot, uid, title) - - def newPlotC(self, tag, uid, title="", pmin=None, pmax=None, - logy=False, stripchart=False, stem=False): - plot = GrDataPlotterC(tag, 32e6, pmin, pmax, stripchart) - plot.semilogy(logy) - plot.stem(stem) - self.createPlot(plot, uid, title) - - def newPlotPsdF(self, tag, uid, title="", pmin=None, pmax=None): - plot = GrDataPlotterPsdF(tag, 32e6, pmin, pmax) - self.createPlot(plot, uid, title) - - def newPlotPsdC(self, tag, uid, title="", pmin=None, pmax=None): - plot = GrDataPlotterPsdC(tag, 32e6, pmin, pmax) - self.createPlot(plot, uid, title) - - def newPlotRasterF(self, tag, uid, title="", pmin=None, pmax=None): - plot = GrTimeRasterF(tag, 32e6, pmin, pmax) - self.createPlot(plot, uid, title) - - def newPlotRasterB(self, tag, uid, title="", pmin=None, pmax=None): - plot = GrTimeRasterB(tag, 32e6, pmin, pmax) - self.createPlot(plot, uid, title) - - def update(self, knobs, uid): - #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys())) - for plot in self.plots[uid]: - data = [] - for n in plot.knobnames: - data.append(knobs[n].value) - plot.update(data) - plot.stop() - plot.wait() - plot.start() - - def setActiveSubWindow(self, window): - if window: - self.mdiArea.setActiveSubWindow(window) - - - def createActions(self): - self.newConAct = QtGui.QAction("&New Connection", - self, shortcut=QtGui.QKeySequence.New, - statusTip="Create a new file", triggered=self.newCon) - #self.newAct = QtGui.QAction(QtGui.QIcon(':/images/new.png'), "&New Plot", - self.newPlotAct = QtGui.QAction("&New Plot", - self, - statusTip="Create a new file", triggered=self.newPlotF) - - self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q", - statusTip="Exit the application", - triggered=QtGui.qApp.closeAllWindows) - - self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4", - statusTip="Close the active window", - triggered=self.mdiArea.closeActiveSubWindow) - - self.closeAllAct = QtGui.QAction("Close &All", self, - statusTip="Close all the windows", - triggered=self.mdiArea.closeAllSubWindows) - - self.urAct = QtGui.QAction("Update Rate", self, shortcut="F5", - statusTip="Change Update Rate", - triggered=self.updateRateShow) - - qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T); - self.tileAct = QtGui.QAction("&Tile", self, - statusTip="Tile the windows", - triggered=self.mdiArea.tileSubWindows, - shortcut=qks) - - qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C); - self.cascadeAct = QtGui.QAction("&Cascade", self, - statusTip="Cascade the windows", shortcut=qks, - triggered=self.mdiArea.cascadeSubWindows) - - self.nextAct = QtGui.QAction("Ne&xt", self, - shortcut=QtGui.QKeySequence.NextChild, - statusTip="Move the focus to the next window", - triggered=self.mdiArea.activateNextSubWindow) - - self.previousAct = QtGui.QAction("Pre&vious", self, - shortcut=QtGui.QKeySequence.PreviousChild, - statusTip="Move the focus to the previous window", - triggered=self.mdiArea.activatePreviousSubWindow) - - self.separatorAct = QtGui.QAction(self) - self.separatorAct.setSeparator(True) - - self.aboutAct = QtGui.QAction("&About", self, - statusTip="Show the application's About box", - triggered=self.about) - - self.aboutQtAct = QtGui.QAction("About &Qt", self, - statusTip="Show the Qt library's About box", - triggered=QtGui.qApp.aboutQt) - - def createMenus(self): - self.fileMenu = self.menuBar().addMenu("&File") - self.fileMenu.addAction(self.newConAct) - self.fileMenu.addAction(self.newPlotAct) - self.fileMenu.addAction(self.urAct) - self.fileMenu.addSeparator() - self.fileMenu.addAction(self.exitAct) - - self.windowMenu = self.menuBar().addMenu("&Window") - self.updateWindowMenu() - self.windowMenu.aboutToShow.connect(self.updateWindowMenu) - - self.menuBar().addSeparator() - - self.helpMenu = self.menuBar().addMenu("&Help") - self.helpMenu.addAction(self.aboutAct) - self.helpMenu.addAction(self.aboutQtAct) - - def updateRateShow(self): - askrate = RateDialog(self.updateRate, self); - if askrate.exec_(): - ur = float(str(askrate.delay.text())); - self.setUpdateRate(ur); - return; - else: - return; - - def createToolBars(self): - self.fileToolBar = self.addToolBar("File") - self.fileToolBar.addAction(self.newConAct) - self.fileToolBar.addAction(self.newPlotAct) - self.fileToolBar.addAction(self.urAct) - - self.fileToolBar = self.addToolBar("Window") - self.fileToolBar.addAction(self.tileAct) - self.fileToolBar.addAction(self.cascadeAct) - - def createStatusBar(self): - self.statusBar().showMessage("Ready") - - - def activeMdiChild(self): - activeSubWindow = self.mdiArea.activeSubWindow() - if activeSubWindow: - return activeSubWindow.widget() - return None - - def updateMenus(self): - hasMdiChild = (self.activeMdiChild() is not None) - self.closeAct.setEnabled(hasMdiChild) - self.closeAllAct.setEnabled(hasMdiChild) - self.tileAct.setEnabled(hasMdiChild) - self.cascadeAct.setEnabled(hasMdiChild) - self.nextAct.setEnabled(hasMdiChild) - self.previousAct.setEnabled(hasMdiChild) - self.separatorAct.setVisible(hasMdiChild) - - def updateWindowMenu(self): - self.windowMenu.clear() - self.windowMenu.addAction(self.closeAct) - self.windowMenu.addAction(self.closeAllAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(self.tileAct) - self.windowMenu.addAction(self.cascadeAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(self.nextAct) - self.windowMenu.addAction(self.previousAct) - self.windowMenu.addAction(self.separatorAct) - - def about(self): - about_info = \ -'''Copyright 2012 Free Software Foundation, Inc.\n -This program is part of GNU Radio.\n -GNU Radio 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; either version 3, or (at your option) any later version.\n -GNU Radio 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.\n -You should have received a copy of the GNU General Public License along with GNU Radio; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.''' - - QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info) - - -class ConInfoDialog(QtGui.QDialog): - def __init__(self, parent=None): - super(ConInfoDialog, self).__init__(parent) - - self.gridLayout = QtGui.QGridLayout(self) - - - self.host = QtGui.QLineEdit(self); - self.port = QtGui.QLineEdit(self); - self.host.setText("localhost"); - self.port.setText("43243"); - - self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) - - self.gridLayout.addWidget(self.host); - self.gridLayout.addWidget(self.port); - self.gridLayout.addWidget(self.buttonBox); - - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) - - - def accept(self): - self.done(1); - - def reject(self): - self.done(0); - - -class UpdaterWindow(QtGui.QDialog): - def __init__(self, key, radio, parent): - QtGui.QDialog.__init__(self, parent) - - self.key = key; - self.radio = radio - - self.resize(300,200) - self.layout = QtGui.QVBoxLayout() - - self.props = radio.properties([key])[key] - info = str(self.props) - - self.infoLabel = QtGui.QLabel(info) - self.layout.addWidget(self.infoLabel) - - # Test here to make sure that a 'set' function - try: - a = radio.set(radio.get([key])) - has_set = True - except Ice.UnknownException: - has_set = False - - if(has_set is False): - self.cancelButton = QtGui.QPushButton("Ok") - self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject) - - self.buttonlayout = QtGui.QHBoxLayout() - self.buttonlayout.addWidget(self.cancelButton) - self.layout.addLayout(self.buttonlayout) - - else: # we have a set function - self.textInput = QtGui.QLineEdit() - self.layout.addWidget(self.textInput) - - self.applyButton = QtGui.QPushButton("Apply") - self.setButton = QtGui.QPushButton("OK") - self.cancelButton = QtGui.QPushButton("Cancel") - - rv = radio.get([key]) - self.textInput.setText(str(rv[key].value)) - self.sv = rv[key] - - self.applyButton.connect(self.applyButton, QtCore.SIGNAL('clicked()'), self._apply) - self.setButton.connect(self.setButton, QtCore.SIGNAL('clicked()'), self._set) - self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject) - - self.is_num = ((type(self.sv.value)==float) or (type(self.sv.value)==int)) - if(self.is_num): - self.sliderlayout = QtGui.QHBoxLayout() - - self.slider = QtGui.QSlider(QtCore.Qt.Horizontal) - - self.sliderlayout.addWidget(QtGui.QLabel(str(self.props.min.value))) - self.sliderlayout.addWidget(self.slider) - self.sliderlayout.addWidget(QtGui.QLabel(str(self.props.max.value))) - - self.steps = 10000 - self.valspan = self.props.max.value - self.props.min.value - - self.slider.setRange(0, 10000) - self._set_slider_value(self.sv.value) - - self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"), self._slide) - - self.layout.addLayout(self.sliderlayout) - - self.buttonlayout = QtGui.QHBoxLayout() - self.buttonlayout.addWidget(self.applyButton) - self.buttonlayout.addWidget(self.setButton) - self.buttonlayout.addWidget(self.cancelButton) - self.layout.addLayout(self.buttonlayout) - - # set layout and go... - self.setLayout(self.layout) - - def _set_slider_value(self, val): - self.slider.setValue(self.steps*(val-self.props.min.value)/self.valspan) - - def _slide(self): - val = (self.slider.value()*self.valspan + self.props.min.value)/float(self.steps) - self.textInput.setText(str(val)) - - def _apply(self): - if(type(self.sv.value) == str): - val = str(self.textInput.text()) - elif(type(self.sv.value) == int): - val = int(round(float(self.textInput.text()))) - elif(type(self.sv.value) == float): - val = float(self.textInput.text()) - else: - sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value))) - sys.exit(-1) - - self.sv.value = val - km = {} - km[self.key] = self.sv - self.radio.set(km) - self._set_slider_value(self.sv.value) - - def _set(self): - self._apply() - self.done(0) - - -class MForm(QtGui.QWidget): - def update(self): - try: - st = time.time(); - knobs = self.radio.get([]); - ft = time.time(); - latency = ft-st; - self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%(latency*1000)) - - except Exception, e: - sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e)) - if(type(self.parent) is MAINWindow): - # Find window of connection - remove = [] - for p in self.parent.mdiArea.subWindowList(): - if self.parent.conns[self.uid] == p.widget(): - remove.append(p) - - # Find any subplot windows of connection - for p in self.parent.mdiArea.subWindowList(): - for plot in self.parent.plots[self.uid]: - if plot.qwidget() == p.widget(): - remove.append(p) - - # Clean up local references to these - self.parent.conns.remove(self.parent.conns[self.uid]) - self.parent.plots.remove(self.parent.plots[self.uid]) - - # Remove subwindows for connection and plots - for r in remove: - self.parent.mdiArea.removeSubWindow(r) - - # Clean up self - self.close() - else: - sys.exit(1) - return - - tableitems = knobs.keys() - - #UPDATE TABLE: - self.table.updateItems(knobs, self.knobprops) - - #UPDATE PLOTS - self.parent.update(knobs, self.uid) - - - def __init__(self, radio=None, port=None, uid=0, updateRate=2000, parent=None): - - super(MForm, self).__init__() - - if(radio == None or port == None): - askinfo = ConInfoDialog(self); - if askinfo.exec_(): - host = str(askinfo.host.text()); - port = str(askinfo.port.text()); - radio = parent.interface.getRadio(host, port) - else: - self.radio = None - return - - self.uid = uid - self.parent = parent - self.horizontalLayout = QtGui.QVBoxLayout(self) - self.gridLayout = QtGui.QGridLayout() - - self.radio = radio - self.knobprops = self.radio.properties([]) - self.parent.knobprops.append(self.knobprops) - self.resize(775,500) - self.timer = QtCore.QTimer() - self.constupdatediv = 0 - self.tableupdatediv = 0 - plotsize=250 - - # make table - self.table = GrDataPlotterValueTable(uid, self, 0, 0, 400, 200) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) - self.table.treeWidget.setSizePolicy(sizePolicy) - self.table.treeWidget.setEditTriggers(QtGui.QAbstractItemView.EditKeyPressed) - self.table.treeWidget.setSortingEnabled(True) - self.table.treeWidget.setDragEnabled(True) - - # add things to layouts - self.horizontalLayout.addWidget(self.table.treeWidget) - - # set up timer - self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update) - self.updateRate = updateRate; - self.timer.start(self.updateRate) - - # set up context menu .. - self.table.treeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - self.table.treeWidget.customContextMenuRequested.connect(self.openMenu) - - # Set up double-click to launch default plotter - self.connect(self.table.treeWidget, - QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'), - self.parent.newSub); - - # Allow drag/drop event from table item to plotter - self.connect(self.table.treeWidget, - QtCore.SIGNAL('itemPressed(QTreeWidgetItem*, int)'), - self.parent.startDrag) - - def openMenu(self, pos): - index = self.table.treeWidget.selectedIndexes() - item = self.table.treeWidget.itemFromIndex(index[0]) - itemname = str(item.text(0)) - self.parent.propertiesMenu(itemname, self.radio, self.uid) - - -class MyClient(IceRadioClient): - def __init__(self): - IceRadioClient.__init__(self, MAINWindow) - -sys.exit(MyClient().main(sys.argv)) diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-perf-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/gr-perf-monitor deleted file mode 100755 index f2c01691a1..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-perf-monitor +++ /dev/null @@ -1,591 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012-2013 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, ctrlport - -from PyQt4 import QtCore,Qt,Qwt5 -import PyQt4.QtGui as QtGui -import sys, time, re, pprint -import itertools -import scipy - -import Ice -from gnuradio.ctrlport.IceRadioClient import * -from gnuradio.ctrlport.GrDataPlotter import * -from gnuradio.ctrlport import GNURadio - -class MAINWindow(QtGui.QMainWindow): - def minimumSizeHint(self): - return QtGui.QSize(800,600) - - def __init__(self, radio, port, interface): - - super(MAINWindow, self).__init__() - self.conns = [] - self.plots = [] - self.knobprops = [] - self.interface = interface - - self.mdiArea = QtGui.QMdiArea() - self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.setCentralWidget(self.mdiArea) - - self.mdiArea.subWindowActivated.connect(self.updateMenus) - self.windowMapper = QtCore.QSignalMapper(self) - self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow) - - self.createActions() - self.createMenus() - self.createToolBars() - self.createStatusBar() - self.updateMenus() - - self.setWindowTitle("GNU Radio Performance Monitor") - self.setUnifiedTitleAndToolBarOnMac(True) - - self.newCon(radio, port) - icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" ) - self.setWindowIcon(icon) - - def newCon(self, radio=None, port=None): - child = MForm(radio, port, len(self.conns), self) - if(child.radio is not None): - child.setWindowTitle(str(child.radio)) - horizbar = QtGui.QScrollArea() - horizbar.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - horizbar.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - horizbar.setWidget(child) - self.mdiArea.addSubWindow(horizbar) - self.mdiArea.currentSubWindow().showMaximized() - - self.conns.append(child) - self.plots.append([]) - - def newUpdater(self, key, radio): - updater = UpdaterWindow(key, radio, None) - updater.setWindowTitle("Updater: " + key) - updater.setModal(False) - updater.exec_() - - def update(self, knobs, uid): - #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys())) - for plot in self.plots[uid]: - data = knobs[plot.name()].value - plot.update(data) - plot.stop() - plot.wait() - plot.start() - - def setActiveSubWindow(self, window): - if window: - self.mdiArea.setActiveSubWindow(window) - - - def createActions(self): - self.newConAct = QtGui.QAction("&New Connection", - self, shortcut=QtGui.QKeySequence.New, - statusTip="Create a new file", triggered=self.newCon) - - self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q", - statusTip="Exit the application", - triggered=QtGui.qApp.closeAllWindows) - - self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4", - statusTip="Close the active window", - triggered=self.mdiArea.closeActiveSubWindow) - - self.closeAllAct = QtGui.QAction("Close &All", self, - statusTip="Close all the windows", - triggered=self.mdiArea.closeAllSubWindows) - - - qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T); - self.tileAct = QtGui.QAction("&Tile", self, - statusTip="Tile the windows", - triggered=self.mdiArea.tileSubWindows, - shortcut=qks) - - qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C); - self.cascadeAct = QtGui.QAction("&Cascade", self, - statusTip="Cascade the windows", shortcut=qks, - triggered=self.mdiArea.cascadeSubWindows) - - self.nextAct = QtGui.QAction("Ne&xt", self, - shortcut=QtGui.QKeySequence.NextChild, - statusTip="Move the focus to the next window", - triggered=self.mdiArea.activateNextSubWindow) - - self.previousAct = QtGui.QAction("Pre&vious", self, - shortcut=QtGui.QKeySequence.PreviousChild, - statusTip="Move the focus to the previous window", - triggered=self.mdiArea.activatePreviousSubWindow) - - self.separatorAct = QtGui.QAction(self) - self.separatorAct.setSeparator(True) - - self.aboutAct = QtGui.QAction("&About", self, - statusTip="Show the application's About box", - triggered=self.about) - - self.aboutQtAct = QtGui.QAction("About &Qt", self, - statusTip="Show the Qt library's About box", - triggered=QtGui.qApp.aboutQt) - - def createMenus(self): - self.fileMenu = self.menuBar().addMenu("&File") - self.fileMenu.addAction(self.newConAct) - self.fileMenu.addSeparator() - self.fileMenu.addAction(self.exitAct) - - self.windowMenu = self.menuBar().addMenu("&Window") - self.updateWindowMenu() - self.windowMenu.aboutToShow.connect(self.updateWindowMenu) - - self.menuBar().addSeparator() - - self.helpMenu = self.menuBar().addMenu("&Help") - self.helpMenu.addAction(self.aboutAct) - self.helpMenu.addAction(self.aboutQtAct) - - def createToolBars(self): - self.fileToolBar = self.addToolBar("File") - self.fileToolBar.addAction(self.newConAct) - - self.fileToolBar = self.addToolBar("Window") - self.fileToolBar.addAction(self.tileAct) - self.fileToolBar.addAction(self.cascadeAct) - - def createStatusBar(self): - self.statusBar().showMessage("Ready") - - - def activeMdiChild(self): - activeSubWindow = self.mdiArea.activeSubWindow() - if activeSubWindow: - return activeSubWindow.widget() - return None - - def updateMenus(self): - hasMdiChild = (self.activeMdiChild() is not None) - self.closeAct.setEnabled(hasMdiChild) - self.closeAllAct.setEnabled(hasMdiChild) - self.tileAct.setEnabled(hasMdiChild) - self.cascadeAct.setEnabled(hasMdiChild) - self.nextAct.setEnabled(hasMdiChild) - self.previousAct.setEnabled(hasMdiChild) - self.separatorAct.setVisible(hasMdiChild) - - def updateWindowMenu(self): - self.windowMenu.clear() - self.windowMenu.addAction(self.closeAct) - self.windowMenu.addAction(self.closeAllAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(self.tileAct) - self.windowMenu.addAction(self.cascadeAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(self.nextAct) - self.windowMenu.addAction(self.previousAct) - self.windowMenu.addAction(self.separatorAct) - - def about(self): - about_info = \ -'''Copyright 2012 Free Software Foundation, Inc.\n -This program is part of GNU Radio.\n -GNU Radio 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; either version 3, or (at your option) any later version.\n -GNU Radio 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.\n -You should have received a copy of the GNU General Public License along with GNU Radio; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.''' - - QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info) - - -class ConInfoDialog(QtGui.QDialog): - def __init__(self, parent=None): - super(ConInfoDialog, self).__init__(parent) - - self.gridLayout = QtGui.QGridLayout(self) - - - self.host = QtGui.QLineEdit(self); - self.port = QtGui.QLineEdit(self); - self.host.setText("localhost"); - self.port.setText("43243"); - - self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | - QtGui.QDialogButtonBox.Cancel) - - self.gridLayout.addWidget(self.host); - self.gridLayout.addWidget(self.port); - self.gridLayout.addWidget(self.buttonBox); - - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) - - - def accept(self): - self.done(1); - - def reject(self): - self.done(0); - - -class UpdaterWindow(QtGui.QDialog): - def __init__(self, key, radio, parent): - QtGui.QDialog.__init__(self, parent) - - self.key = key; - self.radio = radio - - self.resize(300,200) - self.layout = QtGui.QVBoxLayout() - - self.props = radio.properties([key])[key] - info = str(self.props) - - self.infoLabel = QtGui.QLabel(info) - self.layout.addWidget(self.infoLabel) - - self.cancelButton = QtGui.QPushButton("Ok") - self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject) - - self.buttonlayout = QtGui.QHBoxLayout() - self.buttonlayout.addWidget(self.cancelButton) - self.layout.addLayout(self.buttonlayout) - - # set layout and go... - self.setLayout(self.layout) - - def _set_slider_value(self, val): - self.slider.setValue(self.steps*(val-self.props.min.value)/self.valspan) - - def _slide(self): - val = (self.slider.value()*self.valspan + self.props.min.value)/float(self.steps) - self.textInput.setText(str(val)) - - def _apply(self): - if(type(self.sv.value) == str): - val = str(self.textInput.text()) - elif(type(self.sv.value) == int): - val = int(round(float(self.textInput.text()))) - elif(type(self.sv.value) == float): - val = float(self.textInput.text()) - else: - sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value))) - sys.exit(-1) - - self.sv.value = val - km = {} - km[self.key] = self.sv - self.radio.set(km) - self._set_slider_value(self.sv.value) - - def _set(self): - self._apply() - self.done(0) - - -def build_edge_graph(sources, sinks, edges): - ''' - Starting from the sources, walks through all of the edges to find - the next connected block. The output is stored in 'allblocks' - where each row starts with a source and follows one path down - until it terminates in either a sink or as an input to a block - that is part of another chain. - ''' - def find_edge(src, sinks, edges, row, col): - #print "\n\nAll blocks: " - #printer.pprint(allblocks) - #print "\nLooking for: ", src - - src0 = src.split(":")[0] - if(src0 in sinks): - if(len(allblocks) <= row): - allblocks.append(col*[""]) - allblocks[row].append(src) - return row+1 - - for edge in edges: - if(re.match(src0, edge)): - s = edge.split("->")[0] - b = edge.split("->")[1] - if(len(allblocks) <= row): - allblocks.append(col*[""]) - allblocks[row].append(s) - #print "Source: {0} Sink: {1}".format(s, b) - row = find_edge(b, sinks, edges, row, col+1) - return row - - # Recursively get all edges as a matrix of source->sink - n = 0 - allblocks = [] - for src in sources: - n = find_edge(src, sinks, edges, n, 0) - - # Sort by longest list - allblocks = sorted(allblocks, key=len) - allblocks.reverse() - - # Make all rows same length by padding '' in front of sort rows - maxrowlen = len(allblocks[0]) - for i,a in enumerate(allblocks): - rowlen = len(a) - allblocks[i] = (maxrowlen-rowlen)*[''] + a - - # Dedup rows - allblocks = sorted(allblocks) - allblocks = list(k for k,_ in itertools.groupby(allblocks)) - allblocks.reverse() - - return allblocks - - -class MForm(QtGui.QWidget): - def update(self): - try: - st = time.time() - knobs = self.radio.get([b[0] for b in self.block_dict]) - - ft = time.time() - latency = ft-st - self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\ - (latency*1000)) - - except Exception, e: - sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e)) - if(type(self.parent) is MAINWindow): - # Find window of connection - remove = [] - for p in self.parent.mdiArea.subWindowList(): - if self.parent.conns[self.uid] == p.widget(): - remove.append(p) - - # Find any subplot windows of connection - for p in self.parent.mdiArea.subWindowList(): - for plot in self.parent.plots[self.uid]: - if plot.qwidget() == p.widget(): - remove.append(p) - - # Clean up local references to these - self.parent.conns.remove(self.parent.conns[self.uid]) - self.parent.plots.remove(self.parent.plots[self.uid]) - - # Remove subwindows for connection and plots - for r in remove: - self.parent.mdiArea.removeSubWindow(r) - - # Clean up self - self.close() - else: - sys.exit(1) - return - - #UPDATE TABLE: - self.updateItems(knobs) - - #UPDATE PLOTS - self.parent.update(knobs, self.uid) - - def updateItems(self, knobs): - for b in self.block_dict: - if(knobs[b[0]].ice_id.im_class == GNURadio.KnobVecF): - b[1].setText("{0:.4f}".format(knobs[b[0]].value[b[2]])) - else: - b[1].setText("{0:.4f}".format(knobs[b[0]].value)) - - def __init__(self, radio=None, port=None, uid=0, parent=None): - - super(MForm, self).__init__() - - if(radio == None or port == None): - askinfo = ConInfoDialog(self); - if askinfo.exec_(): - host = str(askinfo.host.text()); - port = str(askinfo.port.text()); - radio = parent.interface.getRadio(host, port) - else: - self.radio = None - return - - self.uid = uid - self.parent = parent - self.layout = QtGui.QGridLayout(self) - self.layout.setSizeConstraint(QtGui.QLayout.SetFixedSize) - - self.radio = radio - self.knobprops = self.radio.properties([]) - self.parent.knobprops.append(self.knobprops) - self.resize(775,500) - self.timer = QtCore.QTimer() - self.constupdatediv = 0 - self.tableupdatediv = 0 - plotsize=250 - - - # Set up the graph of blocks - input_name = lambda x: x+"::avg input % full" - output_name = lambda x: x+"::avg output % full" - wtime_name = lambda x: x+"::avg work time" - nout_name = lambda x: x+"::avg noutput_items" - nprod_name = lambda x: x+"::avg nproduced" - - tmplist = [] - knobs = self.radio.get([]) - edgelist = None - for k in knobs: - propname = k.split("::") - blockname = propname[0] - keyname = propname[1] - if(keyname == "edge list"): - edgelist = knobs[k].value - elif(blockname not in tmplist): - # only take gr_blocks (no hier_block2) - if(knobs.has_key(input_name(blockname))): - tmplist.append(blockname) - - if not edgelist: - sys.stderr.write("Could not find list of edges from flowgraph. " + \ - "Make sure the option 'edges_list' is enabled " + \ - "in the ControlPort configuration.\n\n") - sys.exit(1) - - edges = edgelist.split("\n")[0:-1] - producers = [] - consumers = [] - for e in edges: - _e = e.split("->") - producers.append(_e[0]) - consumers.append(_e[1]) - - # Get producers and consumers as sets while ignoring the - # ports. - prods = set(map(lambda x: x.split(":")[0], producers)) - cons = set(map(lambda x: x.split(":")[0], consumers)) - - # Split out all blocks, sources, and sinks based on how they - # appear as consumers and/or producers. - blocks = prods.intersection(cons) - sources = prods.difference(blocks) - sinks = cons.difference(blocks) - - nblocks = len(prods) + len(cons) - - allblocks = build_edge_graph(sources, sinks, edges) - nrows = len(allblocks) - ncols = len(allblocks[0]) - - col_width = 120 - - self.block_dict = [] - - for row, blockrow in enumerate(allblocks): - for col, block in enumerate(blockrow): - if(block == ''): - continue - - bgroup = QtGui.QGroupBox(block) - playout = QtGui.QFormLayout() - bgroup.setLayout(playout) - self.layout.addWidget(bgroup, row, 2*col) - - blockname = block.split(":")[0] - - name = wtime_name(blockname) - wtime = knobs[name].value - newtime = QtGui.QLineEdit() - newtime.setMinimumWidth(col_width) - newtime.setText("{0:.4f}".format(wtime)) - self.block_dict.append((name, newtime)) - - name = nout_name(blockname) - nout = knobs[name].value - newnout = QtGui.QLineEdit() - newnout.setText("{0:.4f}".format(nout)) - newnout.setMinimumWidth(col_width) - self.block_dict.append((name, newnout)) - - name = nprod_name(blockname) - nprod = knobs[name].value - newnprod = QtGui.QLineEdit() - newnprod.setMinimumWidth(col_width) - newnprod.setText("{0:.4f}".format(nprod)) - self.block_dict.append((name, newnprod)) - - playout.addRow("Work time", newtime) - playout.addRow("noutput_items", newnout) - playout.addRow("nproduced", newnprod) - - if blockname in blocks or blockname in sources: - # Add a buffer between blocks - buffgroup = QtGui.QGroupBox("Buffer") - bufflayout = QtGui.QFormLayout() - buffgroup.setLayout(bufflayout) - self.layout.addWidget(buffgroup, row, 2*col+1) - - i = int(block.split(":")[1]) - name = output_name(blockname) - obuff = knobs[name].value - for i,o in enumerate(obuff): - newobuff = QtGui.QLineEdit() - newobuff.setMinimumWidth(col_width) - newobuff.setText("{0:.4f}".format(o)) - self.block_dict.append((name, newobuff, i)) - bufflayout.addRow("Out Buffer {0}".format(i), - newobuff) - - if blockname in blocks or blockname in sinks: - item = self.layout.itemAtPosition(row, 2*col-1) - if(item): - buffgroup = item.widget() - bufflayout = buffgroup.layout() - else: - buffgroup = QtGui.QGroupBox("Buffer") - bufflayout = QtGui.QFormLayout() - buffgroup.setLayout(bufflayout) - self.layout.addWidget(buffgroup, row, 2*col-1) - - i = int(block.split(":")[1]) - name = input_name(blockname) - ibuff = knobs[name].value[i] - newibuff = QtGui.QLineEdit() - newibuff.setMinimumWidth(col_width) - newibuff.setText("{0:.4f}".format(ibuff)) - self.block_dict.append((name, newibuff, i)) - bufflayout.addRow("In Buffer {0}".format(i), - newibuff) - - # set up timer - self.timer = QtCore.QTimer() - self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update) - self.timer.start(1000) - - def openMenu(self, pos): - index = self.table.treeWidget.selectedIndexes() - item = self.table.treeWidget.itemFromIndex(index[0]) - itemname = str(item.text(0)) - self.parent.propertiesMenu(itemname, self.radio, self.uid) - - -class MyClient(IceRadioClient): - def __init__(self): - IceRadioClient.__init__(self, MAINWindow) - -sys.exit(MyClient().main(sys.argv)) diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-perf-monitorx b/gnuradio-core/src/python/gnuradio/ctrlport/gr-perf-monitorx deleted file mode 100755 index a65b0406e4..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-perf-monitorx +++ /dev/null @@ -1,727 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012-2013 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import random,math,operator -import networkx as nx; -import matplotlib.pyplot as plt - -from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas -from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar -from matplotlib.figure import Figure - -from gnuradio import gr, ctrlport - -from PyQt4 import QtCore,Qt,Qwt5 -import PyQt4.QtGui as QtGui -import sys, time, re, pprint -import itertools -import scipy -from scipy import spatial - -import Ice -from gnuradio.ctrlport.IceRadioClient import * -from gnuradio.ctrlport.GrDataPlotter import * -from gnuradio.ctrlport import GNURadio - -class MAINWindow(QtGui.QMainWindow): - def minimumSizeHint(self): - return QtGui.QSize(800,600) - - def __init__(self, radio, port, interface): - - super(MAINWindow, self).__init__() - self.conns = [] - self.plots = [] - self.knobprops = [] - self.interface = interface - - self.mdiArea = QtGui.QMdiArea() - self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.setCentralWidget(self.mdiArea) - - self.mdiArea.subWindowActivated.connect(self.updateMenus) - self.windowMapper = QtCore.QSignalMapper(self) - self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow) - - self.createActions() - self.createMenus() - self.createToolBars() - self.createStatusBar() - self.updateMenus() - - self.setWindowTitle("GNU Radio Performance Monitor") - self.setUnifiedTitleAndToolBarOnMac(True) - - self.newCon(radio, port) - icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" ) - self.setWindowIcon(icon) - - - def newSubWindow(self, window, title): - child = window; - child.setWindowTitle(title) - self.mdiArea.addSubWindow(child) - self.conns.append(child) - child.show(); - self.mdiArea.currentSubWindow().showMaximized() - - - def newCon(self, radio=None, port=None): - child = MForm(radio, port, len(self.conns), self) - if(child.radio is not None): - child.setWindowTitle(str(child.radio)) -# horizbar = QtGui.QScrollArea() -# horizbar.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) -# horizbar.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) -# horizbar.setWidget(child) -# self.mdiArea.addSubWindow(horizbar) - self.mdiArea.addSubWindow(child) - self.mdiArea.currentSubWindow().showMaximized() - - self.conns.append(child) - self.plots.append([]) - - def update(self, knobs, uid): - #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys())) - for plot in self.plots[uid]: - data = knobs[plot.name()].value - plot.update(data) - plot.stop() - plot.wait() - plot.start() - - def setActiveSubWindow(self, window): - if window: - self.mdiArea.setActiveSubWindow(window) - - - def createActions(self): - self.newConAct = QtGui.QAction("&New Connection", - self, shortcut=QtGui.QKeySequence.New, - statusTip="Create a new file", triggered=self.newCon) - - self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q", - statusTip="Exit the application", - triggered=QtGui.qApp.closeAllWindows) - - self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4", - statusTip="Close the active window", - triggered=self.mdiArea.closeActiveSubWindow) - - self.closeAllAct = QtGui.QAction("Close &All", self, - statusTip="Close all the windows", - triggered=self.mdiArea.closeAllSubWindows) - - - qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T); - self.tileAct = QtGui.QAction("&Tile", self, - statusTip="Tile the windows", - triggered=self.mdiArea.tileSubWindows, - shortcut=qks) - - qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C); - self.cascadeAct = QtGui.QAction("&Cascade", self, - statusTip="Cascade the windows", shortcut=qks, - triggered=self.mdiArea.cascadeSubWindows) - - self.nextAct = QtGui.QAction("Ne&xt", self, - shortcut=QtGui.QKeySequence.NextChild, - statusTip="Move the focus to the next window", - triggered=self.mdiArea.activateNextSubWindow) - - self.previousAct = QtGui.QAction("Pre&vious", self, - shortcut=QtGui.QKeySequence.PreviousChild, - statusTip="Move the focus to the previous window", - triggered=self.mdiArea.activatePreviousSubWindow) - - self.separatorAct = QtGui.QAction(self) - self.separatorAct.setSeparator(True) - - self.aboutAct = QtGui.QAction("&About", self, - statusTip="Show the application's About box", - triggered=self.about) - - self.aboutQtAct = QtGui.QAction("About &Qt", self, - statusTip="Show the Qt library's About box", - triggered=QtGui.qApp.aboutQt) - - def createMenus(self): - self.fileMenu = self.menuBar().addMenu("&File") - self.fileMenu.addAction(self.newConAct) - self.fileMenu.addSeparator() - self.fileMenu.addAction(self.exitAct) - - self.windowMenu = self.menuBar().addMenu("&Window") - self.updateWindowMenu() - self.windowMenu.aboutToShow.connect(self.updateWindowMenu) - - self.menuBar().addSeparator() - - self.helpMenu = self.menuBar().addMenu("&Help") - self.helpMenu.addAction(self.aboutAct) - self.helpMenu.addAction(self.aboutQtAct) - - def createToolBars(self): - self.fileToolBar = self.addToolBar("File") - self.fileToolBar.addAction(self.newConAct) - - self.fileToolBar = self.addToolBar("Window") - self.fileToolBar.addAction(self.tileAct) - self.fileToolBar.addAction(self.cascadeAct) - - def createStatusBar(self): - self.statusBar().showMessage("Ready") - - - def activeMdiChild(self): - activeSubWindow = self.mdiArea.activeSubWindow() - if activeSubWindow: - return activeSubWindow.widget() - return None - - def updateMenus(self): - hasMdiChild = (self.activeMdiChild() is not None) - self.closeAct.setEnabled(hasMdiChild) - self.closeAllAct.setEnabled(hasMdiChild) - self.tileAct.setEnabled(hasMdiChild) - self.cascadeAct.setEnabled(hasMdiChild) - self.nextAct.setEnabled(hasMdiChild) - self.previousAct.setEnabled(hasMdiChild) - self.separatorAct.setVisible(hasMdiChild) - - def updateWindowMenu(self): - self.windowMenu.clear() - self.windowMenu.addAction(self.closeAct) - self.windowMenu.addAction(self.closeAllAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(self.tileAct) - self.windowMenu.addAction(self.cascadeAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(self.nextAct) - self.windowMenu.addAction(self.previousAct) - self.windowMenu.addAction(self.separatorAct) - - def about(self): - about_info = \ -'''Copyright 2012 Free Software Foundation, Inc.\n -This program is part of GNU Radio.\n -GNU Radio 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; either version 3, or (at your option) any later version.\n -GNU Radio 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.\n -You should have received a copy of the GNU General Public License along with GNU Radio; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.''' - - QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info) - - -class ConInfoDialog(QtGui.QDialog): - def __init__(self, parent=None): - super(ConInfoDialog, self).__init__(parent) - - self.gridLayout = QtGui.QGridLayout(self) - - - self.host = QtGui.QLineEdit(self); - self.port = QtGui.QLineEdit(self); - self.host.setText("localhost"); - self.port.setText("43243"); - - self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | - QtGui.QDialogButtonBox.Cancel) - - self.gridLayout.addWidget(self.host); - self.gridLayout.addWidget(self.port); - self.gridLayout.addWidget(self.buttonBox); - - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) - - - def accept(self): - self.done(1); - - def reject(self): - self.done(0); - - -class DataTable(QtGui.QWidget): - def update(self): - print "update" - - def __init__(self, radio, G): - QtGui.QWidget.__init__( self) - - self.layout = QtGui.QVBoxLayout(self); - self.hlayout = QtGui.QHBoxLayout(); - self.layout.addLayout(self.hlayout); - - self.G = G; - self.radio = radio; - - self._keymap = None - - # Create a combobox to set the type of statistic we want. - self._statistic = "Instantaneous" - self._statistics_table = {"Instantaneous": "", - "Average": "avg ", - "Variance": "var "} - self.stattype = QtGui.QComboBox() - self.stattype.addItem("Instantaneous") - self.stattype.addItem("Average") - self.stattype.addItem("Variance") - self.stattype.setMaximumWidth(200) - self.hlayout.addWidget(self.stattype); - self.stattype.currentIndexChanged.connect(self.stat_changed) - - # Create a checkbox to toggle sorting of graphs - self._sort = False - self.checksort = QtGui.QCheckBox("Sort") - self.checksort.setCheckState(self._sort) - self.hlayout.addWidget(self.checksort); - self.checksort.stateChanged.connect(self.checksort_changed) - - # set up table - self.perfTable = Qt.QTableWidget(); - self.perfTable.setColumnCount(2) - self.perfTable.verticalHeader().hide(); - self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Runtime"] ); - self.perfTable.horizontalHeader().setStretchLastSection(True); - self.perfTable.setSortingEnabled(True) - nodes = self.G.nodes(data=True) - - # set up plot - self.f = plt.figure(figsize=(10,8), dpi=90) - self.sp = self.f.add_subplot(111); - self.sp.autoscale_view(True,True,True); - self.sp.set_autoscale_on(True) - self.canvas = FigureCanvas(self.f) - - # set up tabs - self.tabber = QtGui.QTabWidget(); - self.layout.addWidget(self.tabber); - self.tabber.addTab(self.perfTable,"Table View"); - self.tabber.addTab(self.canvas, "Graph View"); - - # set up timer - self.timer = QtCore.QTimer() - self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update) - self.timer.start(500) - - for i in range(0,len(nodes)): - self.perfTable.setItem( - i,0, - Qt.QTableWidgetItem(nodes[i][0])) - - def table_update(self,data): - for k in data.keys(): - weight = data[k] - existing = self.perfTable.findItems(str(k),QtCore.Qt.MatchFixedString) - if(len(existing) == 0): - i = self.perfTable.rowCount(); - self.perfTable.setRowCount( i+1) - self.perfTable.setItem( i,0, Qt.QTableWidgetItem(str(k))) - self.perfTable.setItem( i,1, Qt.QTableWidgetItem(str(weight))) - else: - self.perfTable.setItem( self.perfTable.row(existing[0]),1, Qt.QTableWidgetItem(str(weight))) - - def stat_changed(self, index): - self._statistic = str(self.stattype.currentText()) - - def checksort_changed(self, state): - self._sort = state > 0 - -class DataTableBuffers(DataTable): - def __init__(self, radio, G): - DataTable.__init__(self,radio,G) - self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Buffer Full"] ); - - def update(self): - nodes = self.G.nodes(); - - # get buffer fullness for all blocks - kl = map(lambda x: "%s::%soutput %% full" % \ - (x, self._statistics_table[self._statistic]), - nodes); - buf_knobs = self.radio.get(kl) - - # strip values out of ctrlport response - buffer_fullness = dict(zip( - map(lambda x: x.split("::")[0], buf_knobs.keys()), - map(lambda x: x.value, buf_knobs.values()))) - - blockport_fullness = {} - for blk in buffer_fullness: - for port in range(0,len(buffer_fullness[blk])): - blockport_fullness["%s:%d"%(blk,port)] = buffer_fullness[blk][port]; - - self.table_update(blockport_fullness); - - if(self._sort): - sorted_fullness = sorted(blockport_fullness.iteritems(), key=operator.itemgetter(1)) - self._keymap = map(operator.itemgetter(0), sorted_fullness) - else: - if self._keymap: - sorted_fullness = len(self._keymap)*['',] - for b in blockport_fullness: - sorted_fullness[self._keymap.index(b)] = (b, blockport_fullness[b]) - else: - sorted_fullness = blockport_fullness.items() - - self.sp.clear(); - plt.figure(self.f.number) - plt.subplot(111); - self.sp.bar(range(0,len(sorted_fullness)), map(lambda x: x[1], sorted_fullness), - alpha=0.5) - self.sp.set_ylabel("% Buffers Full"); - self.sp.set_xticks( map(lambda x: x+0.5, range(0,len(sorted_fullness)))) - self.sp.set_xticklabels( map(lambda x: " " + x, map(lambda x: x[0], sorted_fullness)), - rotation="vertical", verticalalignment="bottom" ) - self.canvas.draw(); - self.canvas.show(); - -class DataTableRuntimes(DataTable): - def __init__(self, radio, G): - DataTable.__init__(self,radio,G) - #self.perfTable.setRowCount(len( self.G.nodes() )) - - def update(self): - nodes = self.G.nodes(); - - # get work time for all blocks - kl = map(lambda x: "%s::%swork time" % \ - (x, self._statistics_table[self._statistic]), - nodes); - wrk_knobs = self.radio.get(kl) - - # strip values out of ctrlport response - total_work = sum(map(lambda x: x.value, wrk_knobs.values())) - work_times = dict(zip( - map(lambda x: x.split("::")[0], wrk_knobs.keys()), - map(lambda x: x.value/total_work, wrk_knobs.values()))) - - # update table view - self.table_update(work_times) - - if(self._sort): - sorted_work = sorted(work_times.iteritems(), key=operator.itemgetter(1)) - self._keymap = map(operator.itemgetter(0), sorted_work) - else: - if self._keymap: - sorted_work = len(self._keymap)*['',] - for b in work_times: - sorted_work[self._keymap.index(b)] = (b, work_times[b]) - else: - sorted_work = work_times.items() - - self.sp.clear(); - plt.figure(self.f.number) - plt.subplot(111); - self.sp.bar(range(0,len(sorted_work)), map(lambda x: x[1], sorted_work), - alpha=0.5) - self.sp.set_ylabel("% Runtime"); - self.sp.set_xticks( map(lambda x: x+0.5, range(0,len(sorted_work)))) - self.sp.set_xticklabels( map(lambda x: " " + x[0], sorted_work), - rotation="vertical", verticalalignment="bottom" ) - - self.canvas.draw(); - self.canvas.show(); - -class MForm(QtGui.QWidget): - def update(self): - try: - - nodes = self.G.nodes(); - - # get current buffer depths of all output buffers - kl = map(lambda x: "%s::%soutput %% full" % \ - (x, self._statistics_table[self._statistic]), - nodes); - - st = time.time() - buf_knobs = self.radio.get(kl) - td1 = time.time() - st; - - # strip values out of ctrlport response - buf_vals = dict(zip( - map(lambda x: x.split("::")[0], buf_knobs.keys()), - map(lambda x: x.value, buf_knobs.values()))) - - # get work time for all blocks - kl = map(lambda x: "%s::%swork time" % \ - (x, self._statistics_table[self._statistic]), - nodes); - st = time.time() - wrk_knobs = self.radio.get(kl) - td2 = time.time() - st; - - # strip values out of ctrlport response - total_work = sum(map(lambda x: x.value, wrk_knobs.values())) - work_times = dict(zip( - map(lambda x: x.split("::")[0], wrk_knobs.keys()), - map(lambda x: x.value/total_work, wrk_knobs.values()))) - - for n in nodes: - # ne is the list of edges away from this node! - ne = self.G.edges([n],True); - for e in ne: # iterate over edges from this block - # get the right output buffer/port weight for each edge - sourceport = e[2]["sourceport"]; - newweight = buf_vals[n][sourceport] - e[2]["weight"] = newweight; - - # set updated weights - self.node_weights = map(lambda x: 20+2000*work_times[x], nodes); - self.edge_weights = map(lambda x: 100.0*x[2]["weight"], self.G.edges(data=True)); - - # draw graph updates - self.updateGraph(); - - latency = td1 + td2; - self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\ - (latency*1000)) - - except Exception, e: - sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e)) - if(type(self.parent) is MAINWindow): - # Find window of connection - remove = [] - for p in self.parent.mdiArea.subWindowList(): - if self.parent.conns[self.uid] == p.widget(): - remove.append(p) - - # Remove subwindows for connection and plots - for r in remove: - self.parent.mdiArea.removeSubWindow(r) - - # Clean up self - self.close() - else: - sys.exit(1) - return - - def rtt(self): - self.parent.newSubWindow( DataTableRuntimes(self.radio, self.G), "Runtime Table" ); - - def bpt(self): - self.parent.newSubWindow( DataTableBuffers(self.radio, self.G), "Buffers Table" ); - - def stat_changed(self, index): - self._statistic = str(self.stattype.currentText()) - - def __init__(self, radio=None, port=None, uid=0, parent=None): - - super(MForm, self).__init__() - - if(radio == None or port == None): - askinfo = ConInfoDialog(self); - if askinfo.exec_(): - host = str(askinfo.host.text()); - port = str(askinfo.port.text()); - radio = parent.interface.getRadio(host, port) - else: - self.radio = None - return - - - self.uid = uid - self.parent = parent - - self.layoutTop = QtGui.QVBoxLayout(self) - self.ctlBox = QtGui.QHBoxLayout(); - self.layout = QtGui.QHBoxLayout() - - self.layoutTop.addLayout(self.ctlBox); - self.layoutTop.addLayout(self.layout); - - self.rttAct = QtGui.QAction("Runtime Table", - self, statusTip="Runtime Table", triggered=self.rtt) - self.rttBut = Qt.QToolButton() - self.rttBut.setDefaultAction(self.rttAct); - self.ctlBox.addWidget(self.rttBut); - - self.bptAct = QtGui.QAction("Buffer Table", - self, statusTip="Buffer Table", triggered=self.bpt) - self.bptBut = Qt.QToolButton() - self.bptBut.setDefaultAction(self.bptAct); - self.ctlBox.addWidget(self.bptBut); - - self._statistic = "Instantaneous" - self._statistics_table = {"Instantaneous": "", - "Average": "avg ", - "Variance": "var "} - self.stattype = QtGui.QComboBox() - self.stattype.addItem("Instantaneous") - self.stattype.addItem("Average") - self.stattype.addItem("Variance") - self.stattype.setMaximumWidth(200) - self.ctlBox.addWidget(self.stattype); - self.stattype.currentIndexChanged.connect(self.stat_changed) - -# self.setLayout(self.layout); - - self.radio = radio - self.knobprops = self.radio.properties([]) - self.parent.knobprops.append(self.knobprops) - - self.timer = QtCore.QTimer() - self.constupdatediv = 0 - self.tableupdatediv = 0 - plotsize=250 - - - # Set up the graph of blocks - input_name = lambda x: x+"::avg input % full" - output_name = lambda x: x+"::avg output % full" - wtime_name = lambda x: x+"::avg work time" - nout_name = lambda x: x+"::avg noutput_items" - nprod_name = lambda x: x+"::avg nproduced" - - tmplist = [] - knobs = self.radio.get([]) - edgelist = None - for k in knobs: - propname = k.split("::") - blockname = propname[0] - keyname = propname[1] - if(keyname == "edge list"): - edgelist = knobs[k].value - elif(blockname not in tmplist): - # only take gr_blocks (no hier_block2) - if(knobs.has_key(input_name(blockname))): - tmplist.append(blockname) - - if not edgelist: - sys.stderr.write("Could not find list of edges from flowgraph. " + \ - "Make sure the option 'edges_list' is enabled " + \ - "in the ControlPort configuration.\n\n") - sys.exit(1) - - edges = edgelist.split("\n")[0:-1] - edgepairs = []; - for e in edges: - _e = e.split("->") - edgepairs.append( (_e[0].split(":")[0], _e[1].split(":")[0], - {"sourceport":int(_e[0].split(":")[1])}) ); - - self.G = nx.MultiDiGraph(); - self.G.add_edges_from(edgepairs); - - n_edges = self.G.edges(data=True); - for e in n_edges: - e[2]["weight"] = 5+random.random()*10; - - self.G.clear(); - self.G.add_edges_from(n_edges); - - - self.f = plt.figure(figsize=(10,8), dpi=90) - self.sp = self.f.add_subplot(111); - self.sp.autoscale_view(True,True,True); - self.sp.set_autoscale_on(True) - - self.canvas = FigureCanvas(self.f) - self.layout.addWidget(self.canvas); - - self.pos = nx.graphviz_layout(self.G); - #self.pos = nx.pygraphviz_layout(self.G); - #self.pos = nx.spectral_layout(self.G); - #self.pos = nx.circular_layout(self.G); - #self.pos = nx.shell_layout(self.G); - #self.pos = nx.spring_layout(self.G); - - # generate weights and plot - self.update(); - - # set up timer - self.timer = QtCore.QTimer() - self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update) - self.timer.start(1000) - - # Set up mouse callback functions to move blocks around. - self._grabbed = False - self._current_block = '' - self.f.canvas.mpl_connect('button_press_event', - self.button_press) - self.f.canvas.mpl_connect('motion_notify_event', - self.mouse_move) - self.f.canvas.mpl_connect('button_release_event', - self.button_release) - - def button_press(self, event): - x, y = event.xdata, event.ydata - thrsh = 100 - - if(x is not None and y is not None): - nearby = map(lambda z: spatial.distance.euclidean((x,y), z), self.pos.values()) - i = nearby.index(min(nearby)) - if(abs(self.pos.values()[i][0] - x) < thrsh and - abs(self.pos.values()[i][1]-y) < thrsh): - self._current_block = self.pos.keys()[i] - #print "MOVING BLOCK: ", self._current_block - #print "CUR POS: ", self.pos.values()[i] - self._grabbed = True - - def mouse_move(self, event): - if self._grabbed: - x, y = event.xdata, event.ydata - if(x is not None and y is not None): - #print "NEW POS: ", (x,y) - self.pos[self._current_block] = (x,y) - self.updateGraph(); - - def button_release(self, event): - self._grabbed = False - - - def openMenu(self, pos): - index = self.table.treeWidget.selectedIndexes() - item = self.table.treeWidget.itemFromIndex(index[0]) - itemname = str(item.text(0)) - self.parent.propertiesMenu(itemname, self.radio, self.uid) - - def updateGraph(self): - - self.canvas.updateGeometry() - self.sp.clear(); - plt.figure(self.f.number) - plt.subplot(111); - nx.draw(self.G, self.pos, - edge_color=self.edge_weights, - node_color='#A0CBE2', - width=map(lambda x: 3+math.log(x), self.edge_weights), - node_shape="s", - node_size=self.node_weights, - #edge_cmap=plt.cm.Blues, - edge_cmap=plt.cm.Reds, - ax=self.sp, - arrows=False - ) - nx.draw_networkx_labels(self.G, self.pos, - font_size=12) - - self.canvas.draw(); - self.canvas.show(); - -class MyClient(IceRadioClient): - def __init__(self): - IceRadioClient.__init__(self, MAINWindow) - -sys.exit(MyClient().main(sys.argv)) diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/icon.png b/gnuradio-core/src/python/gnuradio/ctrlport/icon.png Binary files differdeleted file mode 100644 index 4beb204428..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/icon.png +++ /dev/null diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/monitor.py b/gnuradio-core/src/python/gnuradio/ctrlport/monitor.py deleted file mode 100644 index 53a571a698..0000000000 --- a/gnuradio-core/src/python/gnuradio/ctrlport/monitor.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import sys, subprocess, re, signal, time, atexit, os -from gnuradio import gr - -class monitor: - def __init__(self): - print "ControlPort Monitor running." - self.started = False - atexit.register(self.shutdown) - - def __del__(self): - if(self.started): - self.stop() - - def start(self): - print "monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints()) - try: - self.proc = subprocess.Popen(map(lambda a: ["gr-ctrlport-monitor", - re.search("\d+\.\d+\.\d+\.\d+",a).group(0), - re.search("-p (\d+)",a).group(1)], - gr.rpcmanager_get().endpoints())[0]) - self.started = True - except: - self.proc = None - print "failed to to start ControlPort Monitor on specified port" - - def stop(self): - if(self.proc): - if(self.proc.returncode == None): - print "\tcalling stop on shutdown" - self.proc.terminate() - else: - print "\tno proc to shut down, exiting" - - def shutdown(self): - print "ctrlport.monitor received shutdown signal" - if(self.started): - self.stop() diff --git a/gnuradio-core/src/python/gnuradio/eng_notation.py b/gnuradio-core/src/python/gnuradio/eng_notation.py deleted file mode 100644 index d23f9005f0..0000000000 --- a/gnuradio-core/src/python/gnuradio/eng_notation.py +++ /dev/null @@ -1,74 +0,0 @@ -# -# Copyright 2003 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# -""" -Display numbers as strings using engineering notation. -""" - -scale_factor = {} -scale_factor['E'] = 1e18 -scale_factor['P'] = 1e15 -scale_factor['T'] = 1e12 -scale_factor['G'] = 1e9 -scale_factor['M'] = 1e6 -scale_factor['k'] = 1e3 -scale_factor['m'] = 1e-3 -scale_factor['u'] = 1e-6 -scale_factor['n'] = 1e-9 -scale_factor['p'] = 1e-12 -scale_factor['f'] = 1e-15 -scale_factor['a'] = 1e-18 - -def num_to_str (n): - '''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n''' - m = abs(n) - if m >= 1e9: - return "%gG" % (n * 1e-9) - elif m >= 1e6: - return "%gM" % (n * 1e-6) - elif m >= 1e3: - return "%gk" % (n * 1e-3) - elif m >= 1: - return "%g" % (n) - elif m >= 1e-3: - return "%gm" % (n * 1e3) - elif m >= 1e-6: - return "%gu" % (n * 1e6) # where's that mu when you need it (unicode?) - elif m >= 1e-9: - return "%gn" % (n * 1e9) - elif m >= 1e-12: - return "%gp" % (n * 1e12) - elif m >= 1e-15: - return "%gf" % (n * 1e15) - else: - return "%g" % (n) - - -def str_to_num (value): - '''Convert a string in engineering notation to a number. E.g., '15m' -> 15e-3''' - try: - scale = 1.0 - suffix = value[-1] - if scale_factor.has_key (suffix): - return float (value[0:-1]) * scale_factor[suffix] - return float (value) - except: - raise RuntimeError ( - "Invalid engineering notation value: %r" % (value,)) diff --git a/gnuradio-core/src/python/gnuradio/eng_option.py b/gnuradio-core/src/python/gnuradio/eng_option.py deleted file mode 100644 index 5d8660f0f2..0000000000 --- a/gnuradio-core/src/python/gnuradio/eng_option.py +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright 2004 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -'''Add support for engineering notation to optparse.OptionParser''' - -from copy import copy -from optparse import Option, OptionValueError -import eng_notation - -def check_eng_float (option, opt, value): - try: - return eng_notation.str_to_num(value) - except: - raise OptionValueError ( - "option %s: invalid engineering notation value: %r" % (opt, value)) - -def check_intx (option, opt, value): - try: - return int (value, 0) - except: - raise OptionValueError ( - "option %s: invalid integer value: %r" % (opt, value)) - -def check_subdev (option, opt, value): - """ - Value has the form: (A|B)(:0|1)? - - Returns: - a 2-tuple (0|1, 0|1) - """ - d = { 'A' : (0, 0), 'A:0' : (0, 0), 'A:1' : (0, 1), 'A:2' : (0, 2), - 'B' : (1, 0), 'B:0' : (1, 0), 'B:1' : (1, 1), 'B:2' : (1, 2) } - try: - return d[value.upper()] - except: - raise OptionValueError( - "option %s: invalid subdev: '%r', must be one of %s" % (opt, value, ', '.join(sorted(d.keys())))) - -class eng_option (Option): - TYPES = Option.TYPES + ("eng_float", "intx", "subdev") - TYPE_CHECKER = copy (Option.TYPE_CHECKER) - TYPE_CHECKER["eng_float"] = check_eng_float - TYPE_CHECKER["intx"] = check_intx - TYPE_CHECKER["subdev"] = check_subdev - diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt deleted file mode 100644 index da22a5f987..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2010-2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -######################################################################## -include(GrPython) - -GR_PYTHON_INSTALL(FILES - __init__.py - exceptions.py - gateway.py - gr_threading.py - gr_threading_23.py - gr_threading_24.py - hier_block2.py - prefs.py - tag_utils.py - top_block.py - pubsub.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr - COMPONENT "core_python" -) - -######################################################################## -# Handle the unit tests -######################################################################## -if(ENABLE_TESTING) -include(GrTest) -file(GLOB py_qa_test_files "qa_*.py") -foreach(py_qa_test_file ${py_qa_test_files}) - get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) -endforeach(py_qa_test_file) -endif(ENABLE_TESTING) diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py deleted file mode 100644 index c468437db7..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2003-2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# The presence of this file turns this directory into a Python package - -""" -Core contents. -""" - -# This is the main GNU Radio python module. -# We pull the swig output and the other modules into the gnuradio.gr namespace - -from gnuradio_core import * -from exceptions import * -from hier_block2 import * -from top_block import * -from gateway import basic_block, sync_block, decim_block, interp_block -from tag_utils import tag_to_python, tag_to_pmt - -# Force the preference database to be initialized -prefs = gr_prefs.singleton diff --git a/gnuradio-core/src/python/gnuradio/gr/exceptions.py b/gnuradio-core/src/python/gnuradio/gr/exceptions.py deleted file mode 100644 index dba04750bc..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/exceptions.py +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright 2004 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -class NotDAG (Exception): - """Not a directed acyclic graph""" - pass - -class CantHappen (Exception): - """Can't happen""" - pass diff --git a/gnuradio-core/src/python/gnuradio/gr/gateway.py b/gnuradio-core/src/python/gnuradio/gr/gateway.py deleted file mode 100644 index c25755bb57..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/gateway.py +++ /dev/null @@ -1,243 +0,0 @@ -# -# Copyright 2011-2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import gnuradio_core as gr_core -from gnuradio_core import io_signature, io_signaturev -from gnuradio_core import gr_block_gw_message_type -from gnuradio_core import block_gateway -import numpy - -######################################################################## -# Magic to turn pointers into numpy arrays -# http://docs.scipy.org/doc/numpy/reference/arrays.interface.html -######################################################################## -def pointer_to_ndarray(addr, dtype, nitems): - class array_like: - __array_interface__ = { - 'data' : (int(addr), False), - 'typestr' : dtype.base.str, - 'descr' : dtype.base.descr, - 'shape' : (nitems,) + dtype.shape, - 'strides' : None, - 'version' : 3 - } - return numpy.asarray(array_like()).view(dtype.base) - -######################################################################## -# Handler that does callbacks from C++ -######################################################################## -class gateway_handler(gr_core.feval_ll): - - #dont put a constructor, it wont work - - def init(self, callback): - self._callback = callback - - def eval(self, arg): - try: self._callback() - except Exception as ex: - print("handler caught exception: %s"%ex) - import traceback; traceback.print_exc() - raise ex - return 0 - -######################################################################## -# Handler that does callbacks from C++ -######################################################################## -class msg_handler(gr_core.feval_p): - - #dont put a constructor, it wont work - - def init(self, callback): - self._callback = callback - - def eval(self, arg): - try: self._callback(arg) - except Exception as ex: - print("handler caught exception: %s"%ex) - import traceback; traceback.print_exc() - raise ex - return 0 - -######################################################################## -# The guts that make this into a gr block -######################################################################## -class gateway_block(object): - - def __init__(self, name, in_sig, out_sig, work_type, factor): - - #ensure that the sigs are iterable dtypes - def sig_to_dtype_sig(sig): - if sig is None: sig = () - return map(numpy.dtype, sig) - self.__in_sig = sig_to_dtype_sig(in_sig) - self.__out_sig = sig_to_dtype_sig(out_sig) - - #cache the ranges to iterate when dispatching work - self.__in_indexes = range(len(self.__in_sig)) - self.__out_indexes = range(len(self.__out_sig)) - - #convert the signatures into gr.io_signatures - def sig_to_gr_io_sigv(sig): - if not len(sig): return io_signature(0, 0, 0) - return io_signaturev(len(sig), len(sig), [s.itemsize for s in sig]) - gr_in_sig = sig_to_gr_io_sigv(self.__in_sig) - gr_out_sig = sig_to_gr_io_sigv(self.__out_sig) - - #create internal gateway block - self.__handler = gateway_handler() - self.__handler.init(self.__gr_block_handle) - self.__gateway = block_gateway( - self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor) - self.__message = self.__gateway.gr_block_message() - - #dict to keep references to all message handlers - self.__msg_handlers = {} - - #register gr_block functions - prefix = 'gr_block__' - for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]: - setattr(self, attr.replace(prefix, ''), getattr(self.__gateway, attr)) - self.pop_msg_queue = lambda: gr_core.gr_block_gw_pop_msg_queue_safe(self.__gateway) - - def to_basic_block(self): - """ - Makes this block connectable by hier/top block python - """ - return self.__gateway.to_basic_block() - - def __gr_block_handle(self): - """ - Dispatch tasks according to the action type specified in the message. - """ - if self.__message.action == gr_block_gw_message_type.ACTION_GENERAL_WORK: - self.__message.general_work_args_return_value = self.general_work( - - input_items=[pointer_to_ndarray( - self.__message.general_work_args_input_items[i], - self.__in_sig[i], - self.__message.general_work_args_ninput_items[i] - ) for i in self.__in_indexes], - - output_items=[pointer_to_ndarray( - self.__message.general_work_args_output_items[i], - self.__out_sig[i], - self.__message.general_work_args_noutput_items - ) for i in self.__out_indexes], - ) - - elif self.__message.action == gr_block_gw_message_type.ACTION_WORK: - self.__message.work_args_return_value = self.work( - - input_items=[pointer_to_ndarray( - self.__message.work_args_input_items[i], - self.__in_sig[i], - self.__message.work_args_ninput_items - ) for i in self.__in_indexes], - - output_items=[pointer_to_ndarray( - self.__message.work_args_output_items[i], - self.__out_sig[i], - self.__message.work_args_noutput_items - ) for i in self.__out_indexes], - ) - - elif self.__message.action == gr_block_gw_message_type.ACTION_FORECAST: - self.forecast( - noutput_items=self.__message.forecast_args_noutput_items, - ninput_items_required=self.__message.forecast_args_ninput_items_required, - ) - - elif self.__message.action == gr_block_gw_message_type.ACTION_START: - self.__message.start_args_return_value = self.start() - - elif self.__message.action == gr_block_gw_message_type.ACTION_STOP: - self.__message.stop_args_return_value = self.stop() - - def forecast(self, noutput_items, ninput_items_required): - """ - forecast is only called from a general block - this is the default implementation - """ - for ninput_item in ninput_items_required: - ninput_item = noutput_items + self.history() - 1; - return - - def general_work(self, *args, **kwargs): - """general work to be overloaded in a derived class""" - raise NotImplementedError("general work not implemented") - - def work(self, *args, **kwargs): - """work to be overloaded in a derived class""" - raise NotImplementedError("work not implemented") - - def start(self): return True - def stop(self): return True - - def set_msg_handler(self, which_port, handler_func): - handler = msg_handler() - handler.init(handler_func) - self.__gateway.set_msg_handler_feval(which_port, handler) - # Save handler object in class so it's not garbage collected - self.__msg_handlers[which_port] = handler - -######################################################################## -# Wrappers for the user to inherit from -######################################################################## -class basic_block(gateway_block): - def __init__(self, name, in_sig, out_sig): - gateway_block.__init__(self, - name=name, - in_sig=in_sig, - out_sig=out_sig, - work_type=gr_core.GR_BLOCK_GW_WORK_GENERAL, - factor=1, #not relevant factor - ) - -class sync_block(gateway_block): - def __init__(self, name, in_sig, out_sig): - gateway_block.__init__(self, - name=name, - in_sig=in_sig, - out_sig=out_sig, - work_type=gr_core.GR_BLOCK_GW_WORK_SYNC, - factor=1, - ) - -class decim_block(gateway_block): - def __init__(self, name, in_sig, out_sig, decim): - gateway_block.__init__(self, - name=name, - in_sig=in_sig, - out_sig=out_sig, - work_type=gr_core.GR_BLOCK_GW_WORK_DECIM, - factor=decim, - ) - -class interp_block(gateway_block): - def __init__(self, name, in_sig, out_sig, interp): - gateway_block.__init__(self, - name=name, - in_sig=in_sig, - out_sig=out_sig, - work_type=gr_core.GR_BLOCK_GW_WORK_INTERP, - factor=interp, - ) diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py deleted file mode 100644 index 5d6f0fdaf9..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/gr_threading.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from sys import version_info as _version_info - -# import patched version of standard threading module - -if _version_info[0:2] == (2, 3): - #print "Importing gr_threading_23" - from gr_threading_23 import * -elif _version_info[0:2] == (2, 4): - #print "Importing gr_threading_24" - from gr_threading_24 import * -else: - # assume the patch was applied... - #print "Importing system provided threading" - from threading import * diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py deleted file mode 100644 index dee8034c1c..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py +++ /dev/null @@ -1,724 +0,0 @@ -"""Thread module emulating a subset of Java's threading model.""" - -# This started life as the threading.py module of Python 2.3 -# It's been patched to fix a problem with join, where a KeyboardInterrupt -# caused a lock to be left in the acquired state. - -import sys as _sys - -try: - import thread -except ImportError: - del _sys.modules[__name__] - raise - -from StringIO import StringIO as _StringIO -from time import time as _time, sleep as _sleep -from traceback import print_exc as _print_exc - -# Rename some stuff so "from threading import *" is safe -__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', - 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', - 'Timer', 'setprofile', 'settrace'] - -_start_new_thread = thread.start_new_thread -_allocate_lock = thread.allocate_lock -_get_ident = thread.get_ident -ThreadError = thread.error -del thread - - -# Debug support (adapted from ihooks.py). -# All the major classes here derive from _Verbose. We force that to -# be a new-style class so that all the major classes here are new-style. -# This helps debugging (type(instance) is more revealing for instances -# of new-style classes). - -_VERBOSE = False - -if __debug__: - - class _Verbose(object): - - def __init__(self, verbose=None): - if verbose is None: - verbose = _VERBOSE - self.__verbose = verbose - - def _note(self, format, *args): - if self.__verbose: - format = format % args - format = "%s: %s\n" % ( - currentThread().getName(), format) - _sys.stderr.write(format) - -else: - # Disable this when using "python -O" - class _Verbose(object): - def __init__(self, verbose=None): - pass - def _note(self, *args): - pass - -# Support for profile and trace hooks - -_profile_hook = None -_trace_hook = None - -def setprofile(func): - global _profile_hook - _profile_hook = func - -def settrace(func): - global _trace_hook - _trace_hook = func - -# Synchronization classes - -Lock = _allocate_lock - -def RLock(*args, **kwargs): - return _RLock(*args, **kwargs) - -class _RLock(_Verbose): - - def __init__(self, verbose=None): - _Verbose.__init__(self, verbose) - self.__block = _allocate_lock() - self.__owner = None - self.__count = 0 - - def __repr__(self): - return "<%s(%s, %d)>" % ( - self.__class__.__name__, - self.__owner and self.__owner.getName(), - self.__count) - - def acquire(self, blocking=1): - me = currentThread() - if self.__owner is me: - self.__count = self.__count + 1 - if __debug__: - self._note("%s.acquire(%s): recursive success", self, blocking) - return 1 - rc = self.__block.acquire(blocking) - if rc: - self.__owner = me - self.__count = 1 - if __debug__: - self._note("%s.acquire(%s): initial succes", self, blocking) - else: - if __debug__: - self._note("%s.acquire(%s): failure", self, blocking) - return rc - - def release(self): - me = currentThread() - assert self.__owner is me, "release() of un-acquire()d lock" - self.__count = count = self.__count - 1 - if not count: - self.__owner = None - self.__block.release() - if __debug__: - self._note("%s.release(): final release", self) - else: - if __debug__: - self._note("%s.release(): non-final release", self) - - # Internal methods used by condition variables - - def _acquire_restore(self, (count, owner)): - self.__block.acquire() - self.__count = count - self.__owner = owner - if __debug__: - self._note("%s._acquire_restore()", self) - - def _release_save(self): - if __debug__: - self._note("%s._release_save()", self) - count = self.__count - self.__count = 0 - owner = self.__owner - self.__owner = None - self.__block.release() - return (count, owner) - - def _is_owned(self): - return self.__owner is currentThread() - - -def Condition(*args, **kwargs): - return _Condition(*args, **kwargs) - -class _Condition(_Verbose): - - def __init__(self, lock=None, verbose=None): - _Verbose.__init__(self, verbose) - if lock is None: - lock = RLock() - self.__lock = lock - # Export the lock's acquire() and release() methods - self.acquire = lock.acquire - self.release = lock.release - # If the lock defines _release_save() and/or _acquire_restore(), - # these override the default implementations (which just call - # release() and acquire() on the lock). Ditto for _is_owned(). - try: - self._release_save = lock._release_save - except AttributeError: - pass - try: - self._acquire_restore = lock._acquire_restore - except AttributeError: - pass - try: - self._is_owned = lock._is_owned - except AttributeError: - pass - self.__waiters = [] - - def __repr__(self): - return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters)) - - def _release_save(self): - self.__lock.release() # No state to save - - def _acquire_restore(self, x): - self.__lock.acquire() # Ignore saved state - - def _is_owned(self): - # Return True if lock is owned by currentThread. - # This method is called only if __lock doesn't have _is_owned(). - if self.__lock.acquire(0): - self.__lock.release() - return False - else: - return True - - def wait(self, timeout=None): - currentThread() # for side-effect - assert self._is_owned(), "wait() of un-acquire()d lock" - waiter = _allocate_lock() - waiter.acquire() - self.__waiters.append(waiter) - saved_state = self._release_save() - try: # restore state no matter what (e.g., KeyboardInterrupt) - if timeout is None: - waiter.acquire() - if __debug__: - self._note("%s.wait(): got it", self) - else: - # Balancing act: We can't afford a pure busy loop, so we - # have to sleep; but if we sleep the whole timeout time, - # we'll be unresponsive. The scheme here sleeps very - # little at first, longer as time goes on, but never longer - # than 20 times per second (or the timeout time remaining). - endtime = _time() + timeout - delay = 0.0005 # 500 us -> initial delay of 1 ms - while True: - gotit = waiter.acquire(0) - if gotit: - break - remaining = endtime - _time() - if remaining <= 0: - break - delay = min(delay * 2, remaining, .05) - _sleep(delay) - if not gotit: - if __debug__: - self._note("%s.wait(%s): timed out", self, timeout) - try: - self.__waiters.remove(waiter) - except ValueError: - pass - else: - if __debug__: - self._note("%s.wait(%s): got it", self, timeout) - finally: - self._acquire_restore(saved_state) - - def notify(self, n=1): - currentThread() # for side-effect - assert self._is_owned(), "notify() of un-acquire()d lock" - __waiters = self.__waiters - waiters = __waiters[:n] - if not waiters: - if __debug__: - self._note("%s.notify(): no waiters", self) - return - self._note("%s.notify(): notifying %d waiter%s", self, n, - n!=1 and "s" or "") - for waiter in waiters: - waiter.release() - try: - __waiters.remove(waiter) - except ValueError: - pass - - def notifyAll(self): - self.notify(len(self.__waiters)) - - -def Semaphore(*args, **kwargs): - return _Semaphore(*args, **kwargs) - -class _Semaphore(_Verbose): - - # After Tim Peters' semaphore class, but not quite the same (no maximum) - - def __init__(self, value=1, verbose=None): - assert value >= 0, "Semaphore initial value must be >= 0" - _Verbose.__init__(self, verbose) - self.__cond = Condition(Lock()) - self.__value = value - - def acquire(self, blocking=1): - rc = False - self.__cond.acquire() - while self.__value == 0: - if not blocking: - break - if __debug__: - self._note("%s.acquire(%s): blocked waiting, value=%s", - self, blocking, self.__value) - self.__cond.wait() - else: - self.__value = self.__value - 1 - if __debug__: - self._note("%s.acquire: success, value=%s", - self, self.__value) - rc = True - self.__cond.release() - return rc - - def release(self): - self.__cond.acquire() - self.__value = self.__value + 1 - if __debug__: - self._note("%s.release: success, value=%s", - self, self.__value) - self.__cond.notify() - self.__cond.release() - - -def BoundedSemaphore(*args, **kwargs): - return _BoundedSemaphore(*args, **kwargs) - -class _BoundedSemaphore(_Semaphore): - """Semaphore that checks that # releases is <= # acquires""" - def __init__(self, value=1, verbose=None): - _Semaphore.__init__(self, value, verbose) - self._initial_value = value - - def release(self): - if self._Semaphore__value >= self._initial_value: - raise ValueError, "Semaphore released too many times" - return _Semaphore.release(self) - - -def Event(*args, **kwargs): - return _Event(*args, **kwargs) - -class _Event(_Verbose): - - # After Tim Peters' event class (without is_posted()) - - def __init__(self, verbose=None): - _Verbose.__init__(self, verbose) - self.__cond = Condition(Lock()) - self.__flag = False - - def isSet(self): - return self.__flag - - def set(self): - self.__cond.acquire() - try: - self.__flag = True - self.__cond.notifyAll() - finally: - self.__cond.release() - - def clear(self): - self.__cond.acquire() - try: - self.__flag = False - finally: - self.__cond.release() - - def wait(self, timeout=None): - self.__cond.acquire() - try: - if not self.__flag: - self.__cond.wait(timeout) - finally: - self.__cond.release() - -# Helper to generate new thread names -_counter = 0 -def _newname(template="Thread-%d"): - global _counter - _counter = _counter + 1 - return template % _counter - -# Active thread administration -_active_limbo_lock = _allocate_lock() -_active = {} -_limbo = {} - - -# Main class for threads - -class Thread(_Verbose): - - __initialized = False - - def __init__(self, group=None, target=None, name=None, - args=(), kwargs={}, verbose=None): - assert group is None, "group argument must be None for now" - _Verbose.__init__(self, verbose) - self.__target = target - self.__name = str(name or _newname()) - self.__args = args - self.__kwargs = kwargs - self.__daemonic = self._set_daemon() - self.__started = False - self.__stopped = False - self.__block = Condition(Lock()) - self.__initialized = True - - def _set_daemon(self): - # Overridden in _MainThread and _DummyThread - return currentThread().isDaemon() - - def __repr__(self): - assert self.__initialized, "Thread.__init__() was not called" - status = "initial" - if self.__started: - status = "started" - if self.__stopped: - status = "stopped" - if self.__daemonic: - status = status + " daemon" - return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) - - def start(self): - assert self.__initialized, "Thread.__init__() not called" - assert not self.__started, "thread already started" - if __debug__: - self._note("%s.start(): starting thread", self) - _active_limbo_lock.acquire() - _limbo[self] = self - _active_limbo_lock.release() - _start_new_thread(self.__bootstrap, ()) - self.__started = True - _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) - - def run(self): - if self.__target: - self.__target(*self.__args, **self.__kwargs) - - def __bootstrap(self): - try: - self.__started = True - _active_limbo_lock.acquire() - _active[_get_ident()] = self - del _limbo[self] - _active_limbo_lock.release() - if __debug__: - self._note("%s.__bootstrap(): thread started", self) - - if _trace_hook: - self._note("%s.__bootstrap(): registering trace hook", self) - _sys.settrace(_trace_hook) - if _profile_hook: - self._note("%s.__bootstrap(): registering profile hook", self) - _sys.setprofile(_profile_hook) - - try: - self.run() - except SystemExit: - if __debug__: - self._note("%s.__bootstrap(): raised SystemExit", self) - except: - if __debug__: - self._note("%s.__bootstrap(): unhandled exception", self) - s = _StringIO() - _print_exc(file=s) - _sys.stderr.write("Exception in thread %s:\n%s\n" % - (self.getName(), s.getvalue())) - else: - if __debug__: - self._note("%s.__bootstrap(): normal return", self) - finally: - self.__stop() - try: - self.__delete() - except: - pass - - def __stop(self): - self.__block.acquire() - self.__stopped = True - self.__block.notifyAll() - self.__block.release() - - def __delete(self): - _active_limbo_lock.acquire() - del _active[_get_ident()] - _active_limbo_lock.release() - - def join(self, timeout=None): - assert self.__initialized, "Thread.__init__() not called" - assert self.__started, "cannot join thread before it is started" - assert self is not currentThread(), "cannot join current thread" - if __debug__: - if not self.__stopped: - self._note("%s.join(): waiting until thread stops", self) - self.__block.acquire() - try: - if timeout is None: - while not self.__stopped: - self.__block.wait() - if __debug__: - self._note("%s.join(): thread stopped", self) - else: - deadline = _time() + timeout - while not self.__stopped: - delay = deadline - _time() - if delay <= 0: - if __debug__: - self._note("%s.join(): timed out", self) - break - self.__block.wait(delay) - else: - if __debug__: - self._note("%s.join(): thread stopped", self) - finally: - self.__block.release() - - def getName(self): - assert self.__initialized, "Thread.__init__() not called" - return self.__name - - def setName(self, name): - assert self.__initialized, "Thread.__init__() not called" - self.__name = str(name) - - def isAlive(self): - assert self.__initialized, "Thread.__init__() not called" - return self.__started and not self.__stopped - - def isDaemon(self): - assert self.__initialized, "Thread.__init__() not called" - return self.__daemonic - - def setDaemon(self, daemonic): - assert self.__initialized, "Thread.__init__() not called" - assert not self.__started, "cannot set daemon status of active thread" - self.__daemonic = daemonic - -# The timer class was contributed by Itamar Shtull-Trauring - -def Timer(*args, **kwargs): - return _Timer(*args, **kwargs) - -class _Timer(Thread): - """Call a function after a specified number of seconds: - - t = Timer(30.0, f, args=[], kwargs={}) - t.start() - t.cancel() # stop the timer's action if it's still waiting - """ - - def __init__(self, interval, function, args=[], kwargs={}): - Thread.__init__(self) - self.interval = interval - self.function = function - self.args = args - self.kwargs = kwargs - self.finished = Event() - - def cancel(self): - """Stop the timer if it hasn't finished yet""" - self.finished.set() - - def run(self): - self.finished.wait(self.interval) - if not self.finished.isSet(): - self.function(*self.args, **self.kwargs) - self.finished.set() - -# Special thread class to represent the main thread -# This is garbage collected through an exit handler - -class _MainThread(Thread): - - def __init__(self): - Thread.__init__(self, name="MainThread") - self._Thread__started = True - _active_limbo_lock.acquire() - _active[_get_ident()] = self - _active_limbo_lock.release() - import atexit - atexit.register(self.__exitfunc) - - def _set_daemon(self): - return False - - def __exitfunc(self): - self._Thread__stop() - t = _pickSomeNonDaemonThread() - if t: - if __debug__: - self._note("%s: waiting for other threads", self) - while t: - t.join() - t = _pickSomeNonDaemonThread() - if __debug__: - self._note("%s: exiting", self) - self._Thread__delete() - -def _pickSomeNonDaemonThread(): - for t in enumerate(): - if not t.isDaemon() and t.isAlive(): - return t - return None - - -# Dummy thread class to represent threads not started here. -# These aren't garbage collected when they die, -# nor can they be waited for. -# Their purpose is to return *something* from currentThread(). -# They are marked as daemon threads so we won't wait for them -# when we exit (conform previous semantics). - -class _DummyThread(Thread): - - def __init__(self): - Thread.__init__(self, name=_newname("Dummy-%d")) - self._Thread__started = True - _active_limbo_lock.acquire() - _active[_get_ident()] = self - _active_limbo_lock.release() - - def _set_daemon(self): - return True - - def join(self, timeout=None): - assert False, "cannot join a dummy thread" - - -# Global API functions - -def currentThread(): - try: - return _active[_get_ident()] - except KeyError: - ##print "currentThread(): no current thread for", _get_ident() - return _DummyThread() - -def activeCount(): - _active_limbo_lock.acquire() - count = len(_active) + len(_limbo) - _active_limbo_lock.release() - return count - -def enumerate(): - _active_limbo_lock.acquire() - active = _active.values() + _limbo.values() - _active_limbo_lock.release() - return active - -# Create the main thread object - -_MainThread() - - -# Self-test code - -def _test(): - - class BoundedQueue(_Verbose): - - def __init__(self, limit): - _Verbose.__init__(self) - self.mon = RLock() - self.rc = Condition(self.mon) - self.wc = Condition(self.mon) - self.limit = limit - self.queue = [] - - def put(self, item): - self.mon.acquire() - while len(self.queue) >= self.limit: - self._note("put(%s): queue full", item) - self.wc.wait() - self.queue.append(item) - self._note("put(%s): appended, length now %d", - item, len(self.queue)) - self.rc.notify() - self.mon.release() - - def get(self): - self.mon.acquire() - while not self.queue: - self._note("get(): queue empty") - self.rc.wait() - item = self.queue.pop(0) - self._note("get(): got %s, %d left", item, len(self.queue)) - self.wc.notify() - self.mon.release() - return item - - class ProducerThread(Thread): - - def __init__(self, queue, quota): - Thread.__init__(self, name="Producer") - self.queue = queue - self.quota = quota - - def run(self): - from random import random - counter = 0 - while counter < self.quota: - counter = counter + 1 - self.queue.put("%s.%d" % (self.getName(), counter)) - _sleep(random() * 0.00001) - - - class ConsumerThread(Thread): - - def __init__(self, queue, count): - Thread.__init__(self, name="Consumer") - self.queue = queue - self.count = count - - def run(self): - while self.count > 0: - item = self.queue.get() - print item - self.count = self.count - 1 - - NP = 3 - QL = 4 - NI = 5 - - Q = BoundedQueue(QL) - P = [] - for i in range(NP): - t = ProducerThread(Q, NI) - t.setName("Producer-%d" % (i+1)) - P.append(t) - C = ConsumerThread(Q, NI*NP) - for t in P: - t.start() - _sleep(0.000001) - C.start() - for t in P: - t.join() - C.join() - -if __name__ == '__main__': - _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py deleted file mode 100644 index 8539bfc047..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py +++ /dev/null @@ -1,793 +0,0 @@ -"""Thread module emulating a subset of Java's threading model.""" - -# This started life as the threading.py module of Python 2.4 -# It's been patched to fix a problem with join, where a KeyboardInterrupt -# caused a lock to be left in the acquired state. - -import sys as _sys - -try: - import thread -except ImportError: - del _sys.modules[__name__] - raise - -from time import time as _time, sleep as _sleep -from traceback import format_exc as _format_exc -from collections import deque - -# Rename some stuff so "from threading import *" is safe -__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', - 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', - 'Timer', 'setprofile', 'settrace', 'local'] - -_start_new_thread = thread.start_new_thread -_allocate_lock = thread.allocate_lock -_get_ident = thread.get_ident -ThreadError = thread.error -del thread - - -# Debug support (adapted from ihooks.py). -# All the major classes here derive from _Verbose. We force that to -# be a new-style class so that all the major classes here are new-style. -# This helps debugging (type(instance) is more revealing for instances -# of new-style classes). - -_VERBOSE = False - -if __debug__: - - class _Verbose(object): - - def __init__(self, verbose=None): - if verbose is None: - verbose = _VERBOSE - self.__verbose = verbose - - def _note(self, format, *args): - if self.__verbose: - format = format % args - format = "%s: %s\n" % ( - currentThread().getName(), format) - _sys.stderr.write(format) - -else: - # Disable this when using "python -O" - class _Verbose(object): - def __init__(self, verbose=None): - pass - def _note(self, *args): - pass - -# Support for profile and trace hooks - -_profile_hook = None -_trace_hook = None - -def setprofile(func): - global _profile_hook - _profile_hook = func - -def settrace(func): - global _trace_hook - _trace_hook = func - -# Synchronization classes - -Lock = _allocate_lock - -def RLock(*args, **kwargs): - return _RLock(*args, **kwargs) - -class _RLock(_Verbose): - - def __init__(self, verbose=None): - _Verbose.__init__(self, verbose) - self.__block = _allocate_lock() - self.__owner = None - self.__count = 0 - - def __repr__(self): - return "<%s(%s, %d)>" % ( - self.__class__.__name__, - self.__owner and self.__owner.getName(), - self.__count) - - def acquire(self, blocking=1): - me = currentThread() - if self.__owner is me: - self.__count = self.__count + 1 - if __debug__: - self._note("%s.acquire(%s): recursive success", self, blocking) - return 1 - rc = self.__block.acquire(blocking) - if rc: - self.__owner = me - self.__count = 1 - if __debug__: - self._note("%s.acquire(%s): initial succes", self, blocking) - else: - if __debug__: - self._note("%s.acquire(%s): failure", self, blocking) - return rc - - def release(self): - me = currentThread() - assert self.__owner is me, "release() of un-acquire()d lock" - self.__count = count = self.__count - 1 - if not count: - self.__owner = None - self.__block.release() - if __debug__: - self._note("%s.release(): final release", self) - else: - if __debug__: - self._note("%s.release(): non-final release", self) - - # Internal methods used by condition variables - - def _acquire_restore(self, (count, owner)): - self.__block.acquire() - self.__count = count - self.__owner = owner - if __debug__: - self._note("%s._acquire_restore()", self) - - def _release_save(self): - if __debug__: - self._note("%s._release_save()", self) - count = self.__count - self.__count = 0 - owner = self.__owner - self.__owner = None - self.__block.release() - return (count, owner) - - def _is_owned(self): - return self.__owner is currentThread() - - -def Condition(*args, **kwargs): - return _Condition(*args, **kwargs) - -class _Condition(_Verbose): - - def __init__(self, lock=None, verbose=None): - _Verbose.__init__(self, verbose) - if lock is None: - lock = RLock() - self.__lock = lock - # Export the lock's acquire() and release() methods - self.acquire = lock.acquire - self.release = lock.release - # If the lock defines _release_save() and/or _acquire_restore(), - # these override the default implementations (which just call - # release() and acquire() on the lock). Ditto for _is_owned(). - try: - self._release_save = lock._release_save - except AttributeError: - pass - try: - self._acquire_restore = lock._acquire_restore - except AttributeError: - pass - try: - self._is_owned = lock._is_owned - except AttributeError: - pass - self.__waiters = [] - - def __repr__(self): - return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters)) - - def _release_save(self): - self.__lock.release() # No state to save - - def _acquire_restore(self, x): - self.__lock.acquire() # Ignore saved state - - def _is_owned(self): - # Return True if lock is owned by currentThread. - # This method is called only if __lock doesn't have _is_owned(). - if self.__lock.acquire(0): - self.__lock.release() - return False - else: - return True - - def wait(self, timeout=None): - assert self._is_owned(), "wait() of un-acquire()d lock" - waiter = _allocate_lock() - waiter.acquire() - self.__waiters.append(waiter) - saved_state = self._release_save() - try: # restore state no matter what (e.g., KeyboardInterrupt) - if timeout is None: - waiter.acquire() - if __debug__: - self._note("%s.wait(): got it", self) - else: - # Balancing act: We can't afford a pure busy loop, so we - # have to sleep; but if we sleep the whole timeout time, - # we'll be unresponsive. The scheme here sleeps very - # little at first, longer as time goes on, but never longer - # than 20 times per second (or the timeout time remaining). - endtime = _time() + timeout - delay = 0.0005 # 500 us -> initial delay of 1 ms - while True: - gotit = waiter.acquire(0) - if gotit: - break - remaining = endtime - _time() - if remaining <= 0: - break - delay = min(delay * 2, remaining, .05) - _sleep(delay) - if not gotit: - if __debug__: - self._note("%s.wait(%s): timed out", self, timeout) - try: - self.__waiters.remove(waiter) - except ValueError: - pass - else: - if __debug__: - self._note("%s.wait(%s): got it", self, timeout) - finally: - self._acquire_restore(saved_state) - - def notify(self, n=1): - assert self._is_owned(), "notify() of un-acquire()d lock" - __waiters = self.__waiters - waiters = __waiters[:n] - if not waiters: - if __debug__: - self._note("%s.notify(): no waiters", self) - return - self._note("%s.notify(): notifying %d waiter%s", self, n, - n!=1 and "s" or "") - for waiter in waiters: - waiter.release() - try: - __waiters.remove(waiter) - except ValueError: - pass - - def notifyAll(self): - self.notify(len(self.__waiters)) - - -def Semaphore(*args, **kwargs): - return _Semaphore(*args, **kwargs) - -class _Semaphore(_Verbose): - - # After Tim Peters' semaphore class, but not quite the same (no maximum) - - def __init__(self, value=1, verbose=None): - assert value >= 0, "Semaphore initial value must be >= 0" - _Verbose.__init__(self, verbose) - self.__cond = Condition(Lock()) - self.__value = value - - def acquire(self, blocking=1): - rc = False - self.__cond.acquire() - while self.__value == 0: - if not blocking: - break - if __debug__: - self._note("%s.acquire(%s): blocked waiting, value=%s", - self, blocking, self.__value) - self.__cond.wait() - else: - self.__value = self.__value - 1 - if __debug__: - self._note("%s.acquire: success, value=%s", - self, self.__value) - rc = True - self.__cond.release() - return rc - - def release(self): - self.__cond.acquire() - self.__value = self.__value + 1 - if __debug__: - self._note("%s.release: success, value=%s", - self, self.__value) - self.__cond.notify() - self.__cond.release() - - -def BoundedSemaphore(*args, **kwargs): - return _BoundedSemaphore(*args, **kwargs) - -class _BoundedSemaphore(_Semaphore): - """Semaphore that checks that # releases is <= # acquires""" - def __init__(self, value=1, verbose=None): - _Semaphore.__init__(self, value, verbose) - self._initial_value = value - - def release(self): - if self._Semaphore__value >= self._initial_value: - raise ValueError, "Semaphore released too many times" - return _Semaphore.release(self) - - -def Event(*args, **kwargs): - return _Event(*args, **kwargs) - -class _Event(_Verbose): - - # After Tim Peters' event class (without is_posted()) - - def __init__(self, verbose=None): - _Verbose.__init__(self, verbose) - self.__cond = Condition(Lock()) - self.__flag = False - - def isSet(self): - return self.__flag - - def set(self): - self.__cond.acquire() - try: - self.__flag = True - self.__cond.notifyAll() - finally: - self.__cond.release() - - def clear(self): - self.__cond.acquire() - try: - self.__flag = False - finally: - self.__cond.release() - - def wait(self, timeout=None): - self.__cond.acquire() - try: - if not self.__flag: - self.__cond.wait(timeout) - finally: - self.__cond.release() - -# Helper to generate new thread names -_counter = 0 -def _newname(template="Thread-%d"): - global _counter - _counter = _counter + 1 - return template % _counter - -# Active thread administration -_active_limbo_lock = _allocate_lock() -_active = {} -_limbo = {} - - -# Main class for threads - -class Thread(_Verbose): - - __initialized = False - # Need to store a reference to sys.exc_info for printing - # out exceptions when a thread tries to use a global var. during interp. - # shutdown and thus raises an exception about trying to perform some - # operation on/with a NoneType - __exc_info = _sys.exc_info - - def __init__(self, group=None, target=None, name=None, - args=(), kwargs={}, verbose=None): - assert group is None, "group argument must be None for now" - _Verbose.__init__(self, verbose) - self.__target = target - self.__name = str(name or _newname()) - self.__args = args - self.__kwargs = kwargs - self.__daemonic = self._set_daemon() - self.__started = False - self.__stopped = False - self.__block = Condition(Lock()) - self.__initialized = True - # sys.stderr is not stored in the class like - # sys.exc_info since it can be changed between instances - self.__stderr = _sys.stderr - - def _set_daemon(self): - # Overridden in _MainThread and _DummyThread - return currentThread().isDaemon() - - def __repr__(self): - assert self.__initialized, "Thread.__init__() was not called" - status = "initial" - if self.__started: - status = "started" - if self.__stopped: - status = "stopped" - if self.__daemonic: - status = status + " daemon" - return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) - - def start(self): - assert self.__initialized, "Thread.__init__() not called" - assert not self.__started, "thread already started" - if __debug__: - self._note("%s.start(): starting thread", self) - _active_limbo_lock.acquire() - _limbo[self] = self - _active_limbo_lock.release() - _start_new_thread(self.__bootstrap, ()) - self.__started = True - _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) - - def run(self): - if self.__target: - self.__target(*self.__args, **self.__kwargs) - - def __bootstrap(self): - try: - self.__started = True - _active_limbo_lock.acquire() - _active[_get_ident()] = self - del _limbo[self] - _active_limbo_lock.release() - if __debug__: - self._note("%s.__bootstrap(): thread started", self) - - if _trace_hook: - self._note("%s.__bootstrap(): registering trace hook", self) - _sys.settrace(_trace_hook) - if _profile_hook: - self._note("%s.__bootstrap(): registering profile hook", self) - _sys.setprofile(_profile_hook) - - try: - self.run() - except SystemExit: - if __debug__: - self._note("%s.__bootstrap(): raised SystemExit", self) - except: - if __debug__: - self._note("%s.__bootstrap(): unhandled exception", self) - # If sys.stderr is no more (most likely from interpreter - # shutdown) use self.__stderr. Otherwise still use sys (as in - # _sys) in case sys.stderr was redefined since the creation of - # self. - if _sys: - _sys.stderr.write("Exception in thread %s:\n%s\n" % - (self.getName(), _format_exc())) - else: - # Do the best job possible w/o a huge amt. of code to - # approximate a traceback (code ideas from - # Lib/traceback.py) - exc_type, exc_value, exc_tb = self.__exc_info() - try: - print>>self.__stderr, ( - "Exception in thread " + self.getName() + - " (most likely raised during interpreter shutdown):") - print>>self.__stderr, ( - "Traceback (most recent call last):") - while exc_tb: - print>>self.__stderr, ( - ' File "%s", line %s, in %s' % - (exc_tb.tb_frame.f_code.co_filename, - exc_tb.tb_lineno, - exc_tb.tb_frame.f_code.co_name)) - exc_tb = exc_tb.tb_next - print>>self.__stderr, ("%s: %s" % (exc_type, exc_value)) - # Make sure that exc_tb gets deleted since it is a memory - # hog; deleting everything else is just for thoroughness - finally: - del exc_type, exc_value, exc_tb - else: - if __debug__: - self._note("%s.__bootstrap(): normal return", self) - finally: - self.__stop() - try: - self.__delete() - except: - pass - - def __stop(self): - self.__block.acquire() - self.__stopped = True - self.__block.notifyAll() - self.__block.release() - - def __delete(self): - "Remove current thread from the dict of currently running threads." - - # Notes about running with dummy_thread: - # - # Must take care to not raise an exception if dummy_thread is being - # used (and thus this module is being used as an instance of - # dummy_threading). dummy_thread.get_ident() always returns -1 since - # there is only one thread if dummy_thread is being used. Thus - # len(_active) is always <= 1 here, and any Thread instance created - # overwrites the (if any) thread currently registered in _active. - # - # An instance of _MainThread is always created by 'threading'. This - # gets overwritten the instant an instance of Thread is created; both - # threads return -1 from dummy_thread.get_ident() and thus have the - # same key in the dict. So when the _MainThread instance created by - # 'threading' tries to clean itself up when atexit calls this method - # it gets a KeyError if another Thread instance was created. - # - # This all means that KeyError from trying to delete something from - # _active if dummy_threading is being used is a red herring. But - # since it isn't if dummy_threading is *not* being used then don't - # hide the exception. - - _active_limbo_lock.acquire() - try: - try: - del _active[_get_ident()] - except KeyError: - if 'dummy_threading' not in _sys.modules: - raise - finally: - _active_limbo_lock.release() - - def join(self, timeout=None): - assert self.__initialized, "Thread.__init__() not called" - assert self.__started, "cannot join thread before it is started" - assert self is not currentThread(), "cannot join current thread" - if __debug__: - if not self.__stopped: - self._note("%s.join(): waiting until thread stops", self) - self.__block.acquire() - try: - if timeout is None: - while not self.__stopped: - self.__block.wait() - if __debug__: - self._note("%s.join(): thread stopped", self) - else: - deadline = _time() + timeout - while not self.__stopped: - delay = deadline - _time() - if delay <= 0: - if __debug__: - self._note("%s.join(): timed out", self) - break - self.__block.wait(delay) - else: - if __debug__: - self._note("%s.join(): thread stopped", self) - finally: - self.__block.release() - - def getName(self): - assert self.__initialized, "Thread.__init__() not called" - return self.__name - - def setName(self, name): - assert self.__initialized, "Thread.__init__() not called" - self.__name = str(name) - - def isAlive(self): - assert self.__initialized, "Thread.__init__() not called" - return self.__started and not self.__stopped - - def isDaemon(self): - assert self.__initialized, "Thread.__init__() not called" - return self.__daemonic - - def setDaemon(self, daemonic): - assert self.__initialized, "Thread.__init__() not called" - assert not self.__started, "cannot set daemon status of active thread" - self.__daemonic = daemonic - -# The timer class was contributed by Itamar Shtull-Trauring - -def Timer(*args, **kwargs): - return _Timer(*args, **kwargs) - -class _Timer(Thread): - """Call a function after a specified number of seconds: - - t = Timer(30.0, f, args=[], kwargs={}) - t.start() - t.cancel() # stop the timer's action if it's still waiting - """ - - def __init__(self, interval, function, args=[], kwargs={}): - Thread.__init__(self) - self.interval = interval - self.function = function - self.args = args - self.kwargs = kwargs - self.finished = Event() - - def cancel(self): - """Stop the timer if it hasn't finished yet""" - self.finished.set() - - def run(self): - self.finished.wait(self.interval) - if not self.finished.isSet(): - self.function(*self.args, **self.kwargs) - self.finished.set() - -# Special thread class to represent the main thread -# This is garbage collected through an exit handler - -class _MainThread(Thread): - - def __init__(self): - Thread.__init__(self, name="MainThread") - self._Thread__started = True - _active_limbo_lock.acquire() - _active[_get_ident()] = self - _active_limbo_lock.release() - import atexit - atexit.register(self.__exitfunc) - - def _set_daemon(self): - return False - - def __exitfunc(self): - self._Thread__stop() - t = _pickSomeNonDaemonThread() - if t: - if __debug__: - self._note("%s: waiting for other threads", self) - while t: - t.join() - t = _pickSomeNonDaemonThread() - if __debug__: - self._note("%s: exiting", self) - self._Thread__delete() - -def _pickSomeNonDaemonThread(): - for t in enumerate(): - if not t.isDaemon() and t.isAlive(): - return t - return None - - -# Dummy thread class to represent threads not started here. -# These aren't garbage collected when they die, -# nor can they be waited for. -# Their purpose is to return *something* from currentThread(). -# They are marked as daemon threads so we won't wait for them -# when we exit (conform previous semantics). - -class _DummyThread(Thread): - - def __init__(self): - Thread.__init__(self, name=_newname("Dummy-%d")) - self._Thread__started = True - _active_limbo_lock.acquire() - _active[_get_ident()] = self - _active_limbo_lock.release() - - def _set_daemon(self): - return True - - def join(self, timeout=None): - assert False, "cannot join a dummy thread" - - -# Global API functions - -def currentThread(): - try: - return _active[_get_ident()] - except KeyError: - ##print "currentThread(): no current thread for", _get_ident() - return _DummyThread() - -def activeCount(): - _active_limbo_lock.acquire() - count = len(_active) + len(_limbo) - _active_limbo_lock.release() - return count - -def enumerate(): - _active_limbo_lock.acquire() - active = _active.values() + _limbo.values() - _active_limbo_lock.release() - return active - -# Create the main thread object - -_MainThread() - -# get thread-local implementation, either from the thread -# module, or from the python fallback - -try: - from thread import _local as local -except ImportError: - from _threading_local import local - - -# Self-test code - -def _test(): - - class BoundedQueue(_Verbose): - - def __init__(self, limit): - _Verbose.__init__(self) - self.mon = RLock() - self.rc = Condition(self.mon) - self.wc = Condition(self.mon) - self.limit = limit - self.queue = deque() - - def put(self, item): - self.mon.acquire() - while len(self.queue) >= self.limit: - self._note("put(%s): queue full", item) - self.wc.wait() - self.queue.append(item) - self._note("put(%s): appended, length now %d", - item, len(self.queue)) - self.rc.notify() - self.mon.release() - - def get(self): - self.mon.acquire() - while not self.queue: - self._note("get(): queue empty") - self.rc.wait() - item = self.queue.popleft() - self._note("get(): got %s, %d left", item, len(self.queue)) - self.wc.notify() - self.mon.release() - return item - - class ProducerThread(Thread): - - def __init__(self, queue, quota): - Thread.__init__(self, name="Producer") - self.queue = queue - self.quota = quota - - def run(self): - from random import random - counter = 0 - while counter < self.quota: - counter = counter + 1 - self.queue.put("%s.%d" % (self.getName(), counter)) - _sleep(random() * 0.00001) - - - class ConsumerThread(Thread): - - def __init__(self, queue, count): - Thread.__init__(self, name="Consumer") - self.queue = queue - self.count = count - - def run(self): - while self.count > 0: - item = self.queue.get() - print item - self.count = self.count - 1 - - NP = 3 - QL = 4 - NI = 5 - - Q = BoundedQueue(QL) - P = [] - for i in range(NP): - t = ProducerThread(Q, NI) - t.setName("Producer-%d" % (i+1)) - P.append(t) - C = ConsumerThread(Q, NI*NP) - for t in P: - t.start() - _sleep(0.000001) - C.start() - for t in P: - t.join() - C.join() - -if __name__ == '__main__': - _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py deleted file mode 100644 index ff39b3e709..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py +++ /dev/null @@ -1,132 +0,0 @@ -# -# Copyright 2006,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio_core import hier_block2_swig - -try: - import pmt -except ImportError: - from gruel import pmt - -# -# This hack forces a 'has-a' relationship to look like an 'is-a' one. -# -# It allows Python classes to subclass this one, while passing through -# method calls to the C++ class shared pointer from SWIG. -# -# It also allows us to intercept method calls if needed -# -class hier_block2(object): - """ - Subclass this to create a python hierarchical block. - - This is a python wrapper around the C++ hierarchical block implementation. - Provides convenience functions and allows proper Python subclassing. - """ - - def __init__(self, name, input_signature, output_signature): - """ - Create a hierarchical block with a given name and I/O signatures. - """ - self._hb = hier_block2_swig(name, input_signature, output_signature) - - def __getattr__(self, name): - """ - Pass-through member requests to the C++ object. - """ - if not hasattr(self, "_hb"): - raise RuntimeError("hier_block2: invalid state--did you forget to call gr.hier_block2.__init__ in a derived class?") - return getattr(self._hb, name) - - def connect(self, *points): - """ - Connect two or more block endpoints. An endpoint is either a (block, port) - tuple or a block instance. In the latter case, the port number is assumed - to be zero. - - To connect the hierarchical block external inputs or outputs to internal block - inputs or outputs, use 'self' in the connect call. - - If multiple arguments are provided, connect will attempt to wire them in series, - interpreting the endpoints as inputs or outputs as appropriate. - """ - - if len (points) < 1: - raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),)) - else: - if len(points) == 1: - self._hb.primitive_connect(points[0].to_basic_block()) - else: - for i in range (1, len (points)): - self._connect(points[i-1], points[i]) - - def _connect(self, src, dst): - (src_block, src_port) = self._coerce_endpoint(src) - (dst_block, dst_port) = self._coerce_endpoint(dst) - self._hb.primitive_connect(src_block.to_basic_block(), src_port, - dst_block.to_basic_block(), dst_port) - - def _coerce_endpoint(self, endp): - if hasattr(endp, 'to_basic_block'): - return (endp, 0) - else: - if hasattr(endp, "__getitem__") and len(endp) == 2: - return endp # Assume user put (block, port) - else: - raise ValueError("unable to coerce endpoint") - - def disconnect(self, *points): - """ - Disconnect two endpoints in the flowgraph. - - To disconnect the hierarchical block external inputs or outputs to internal block - inputs or outputs, use 'self' in the connect call. - - If more than two arguments are provided, they are disconnected successively. - """ - - if len (points) < 1: - raise ValueError, ("disconnect requires at least one endpoint; %d provided." % (len (points),)) - else: - if len (points) == 1: - self._hb.primitive_disconnect(points[0].to_basic_block()) - else: - for i in range (1, len (points)): - self._disconnect(points[i-1], points[i]) - - def _disconnect(self, src, dst): - (src_block, src_port) = self._coerce_endpoint(src) - (dst_block, dst_port) = self._coerce_endpoint(dst) - self._hb.primitive_disconnect(src_block.to_basic_block(), src_port, - dst_block.to_basic_block(), dst_port) - - def msg_connect(self, src, srcport, dst, dstport): - self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); - - def msg_disconnect(self, src, srcport, dst, dstport): - self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); - - def message_port_register_hier_in(self, portname): - self.primitive_message_port_register_hier_in(pmt.intern(portname)); - - def message_port_register_hier_out(self, portname): - self.primitive_message_port_register_hier_out(pmt.intern(portname)); - diff --git a/gnuradio-core/src/python/gnuradio/gr/prefs.py b/gnuradio-core/src/python/gnuradio/gr/prefs.py deleted file mode 100644 index 25fa8cd6ae..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/prefs.py +++ /dev/null @@ -1,127 +0,0 @@ -# -# Copyright 2006,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import gnuradio_core as gsp -_prefs_base = gsp.gr_prefs - - -import ConfigParser -import os -import os.path -import sys -import glob - - -def _user_prefs_filename(): - return os.path.expanduser('~/.gnuradio/config.conf') - -def _sys_prefs_dirname(): - return gsp.prefsdir() - -def _bool(x): - """ - Try to coerce obj to a True or False - """ - if isinstance(x, bool): - return x - if isinstance(x, (float, int)): - return bool(x) - raise TypeError, x - - -class _prefs(_prefs_base): - """ - Derive our 'real class' from the stubbed out base class that has support - for SWIG directors. This allows C++ code to magically and transparently - invoke the methods in this python class. - """ - def __init__(self): - _prefs_base.__init__(self) - self.cp = ConfigParser.RawConfigParser() - self.__getattr__ = lambda self, name: getattr(self.cp, name) - - def _sys_prefs_filenames(self): - dir = _sys_prefs_dirname() - try: - fnames = glob.glob(os.path.join(dir, '*.conf')) - except (IOError, OSError): - return [] - fnames.sort() - return fnames - - def _read_files(self): - filenames = self._sys_prefs_filenames() - filenames.append(_user_prefs_filename()) - #print "filenames: ", filenames - self.cp.read(filenames) - - # ---------------------------------------------------------------- - # These methods override the C++ virtual methods of the same name - # ---------------------------------------------------------------- - def has_section(self, section): - return self.cp.has_section(section) - - def has_option(self, section, option): - return self.cp.has_option(section, option) - - def get_string(self, section, option, default_val): - try: - return self.cp.get(section, option) - except: - return default_val - - def get_bool(self, section, option, default_val): - try: - return self.cp.getboolean(section, option) - except: - return default_val - - def get_long(self, section, option, default_val): - try: - return self.cp.getint(section, option) - except: - return default_val - - def get_double(self, section, option, default_val): - try: - return self.cp.getfloat(section, option) - except: - return default_val - # ---------------------------------------------------------------- - # End override of C++ virtual methods - # ---------------------------------------------------------------- - - -_prefs_db = _prefs() - -# if GR_DONT_LOAD_PREFS is set, don't load them. -# (make check uses this to avoid interactions.) -if os.getenv("GR_DONT_LOAD_PREFS", None) is None: - _prefs_db._read_files() - - -_prefs_base.set_singleton(_prefs_db) # tell C++ what instance to use - -def prefs(): - """ - Return the global preference data base - """ - return _prefs_db diff --git a/gnuradio-core/src/python/gnuradio/gr/pubsub.py b/gnuradio-core/src/python/gnuradio/gr/pubsub.py deleted file mode 100644 index 90568418fc..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/pubsub.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -Abstract GNU Radio publisher/subscriber interface - -This is a proof of concept implementation, will likely change significantly. -""" - -class pubsub(dict): - def __init__(self): - self._publishers = { } - self._subscribers = { } - self._proxies = { } - - def __missing__(self, key, value=None): - dict.__setitem__(self, key, value) - self._publishers[key] = None - self._subscribers[key] = [] - self._proxies[key] = None - - def __setitem__(self, key, val): - if not self.has_key(key): - self.__missing__(key, val) - elif self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - p[newkey] = val - else: - dict.__setitem__(self, key, val) - for sub in self._subscribers[key]: - # Note this means subscribers will get called in the thread - # context of the 'set' caller. - sub(val) - - def __getitem__(self, key): - if not self.has_key(key): self.__missing__(key) - if self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - return p[newkey] - elif self._publishers[key] is not None: - return self._publishers[key]() - else: - return dict.__getitem__(self, key) - - def publish(self, key, publisher): - if not self.has_key(key): self.__missing__(key) - if self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - p.publish(newkey, publisher) - else: - self._publishers[key] = publisher - - def subscribe(self, key, subscriber): - if not self.has_key(key): self.__missing__(key) - if self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - p.subscribe(newkey, subscriber) - else: - self._subscribers[key].append(subscriber) - - def unpublish(self, key): - if self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - p.unpublish(newkey) - else: - self._publishers[key] = None - - def unsubscribe(self, key, subscriber): - if self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - p.unsubscribe(newkey, subscriber) - else: - self._subscribers[key].remove(subscriber) - - def proxy(self, key, p, newkey=None): - if not self.has_key(key): self.__missing__(key) - if newkey is None: newkey = key - self._proxies[key] = (p, newkey) - - def unproxy(self, key): - self._proxies[key] = None - -# Test code -if __name__ == "__main__": - import sys - o = pubsub() - - # Non-existent key gets auto-created with None value - print "Auto-created key 'foo' value:", o['foo'] - - # Add some subscribers - # First is a bare function - def print_len(x): - print "len=%i" % (len(x), ) - o.subscribe('foo', print_len) - - # The second is a class member function - class subber(object): - def __init__(self, param): - self._param = param - def printer(self, x): - print self._param, `x` - s = subber('param') - o.subscribe('foo', s.printer) - - # The third is a lambda function - o.subscribe('foo', lambda x: sys.stdout.write('val='+`x`+'\n')) - - # Update key 'foo', will notify subscribers - print "Updating 'foo' with three subscribers:" - o['foo'] = 'bar'; - - # Remove first subscriber - o.unsubscribe('foo', print_len) - - # Update now will only trigger second and third subscriber - print "Updating 'foo' after removing a subscriber:" - o['foo'] = 'bar2'; - - # Publish a key as a function, in this case, a lambda function - o.publish('baz', lambda : 42) - print "Published value of 'baz':", o['baz'] - - # Unpublish the key - o.unpublish('baz') - - # This will return None, as there is no publisher - print "Value of 'baz' with no publisher:", o['baz'] - - # Set 'baz' key, it gets cached - o['baz'] = 'bazzz' - - # Now will return cached value, since no provider - print "Cached value of 'baz' after being set:", o['baz'] diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_feval.py b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py deleted file mode 100755 index 9018e12f36..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_feval.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2006,2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class my_add2_dd(gr.feval_dd): - def eval(self, x): - return x + 2 - -class my_add2_ll(gr.feval_ll): - def eval(self, x): - return x + 2 - -class my_add2_cc(gr.feval_cc): - def eval(self, x): - return x + (2 - 2j) - -class my_feval(gr.feval): - def __init__(self): - gr.feval.__init__(self) - self.fired = False - def eval(self): - self.fired = True - -class test_feval(gr_unittest.TestCase): - - def test_dd_1(self): - f = my_add2_dd() - src_data = (0.0, 1.0, 2.0, 3.0, 4.0) - expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) - # this is all in python... - actual_result = tuple([f.eval(x) for x in src_data]) - self.assertEqual(expected_result, actual_result) - - def test_dd_2(self): - f = my_add2_dd() - src_data = (0.0, 1.0, 2.0, 3.0, 4.0) - expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) - # this is python -> C++ -> python and back again... - actual_result = tuple([gr.feval_dd_example(f, x) for x in src_data]) - self.assertEqual(expected_result, actual_result) - - - def test_ll_1(self): - f = my_add2_ll() - src_data = (0, 1, 2, 3, 4) - expected_result = (2, 3, 4, 5, 6) - # this is all in python... - actual_result = tuple([f.eval(x) for x in src_data]) - self.assertEqual(expected_result, actual_result) - - def test_ll_2(self): - f = my_add2_ll() - src_data = (0, 1, 2, 3, 4) - expected_result = (2, 3, 4, 5, 6) - # this is python -> C++ -> python and back again... - actual_result = tuple([gr.feval_ll_example(f, x) for x in src_data]) - self.assertEqual(expected_result, actual_result) - - - def test_cc_1(self): - f = my_add2_cc() - src_data = (0+1j, 2+3j, 4+5j, 6+7j) - expected_result = (2-1j, 4+1j, 6+3j, 8+5j) - # this is all in python... - actual_result = tuple([f.eval(x) for x in src_data]) - self.assertEqual(expected_result, actual_result) - - def test_cc_2(self): - f = my_add2_cc() - src_data = (0+1j, 2+3j, 4+5j, 6+7j) - expected_result = (2-1j, 4+1j, 6+3j, 8+5j) - # this is python -> C++ -> python and back again... - actual_result = tuple([gr.feval_cc_example(f, x) for x in src_data]) - self.assertEqual(expected_result, actual_result) - - def test_void_1(self): - # this is all in python - f = my_feval() - f.eval() - self.assertEqual(True, f.fired) - - def test_void_2(self): - # this is python -> C++ -> python and back again - f = my_feval() - gr.feval_example(f) - self.assertEqual(True, f.fired) - - -if __name__ == '__main__': - gr_unittest.run(test_feval, "test_feval.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py deleted file mode 100755 index f80188c9fc..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2008,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class test_kludged_imports (gr_unittest.TestCase): - - def setUp(self): - pass - - def tearDown(self): - pass - - def test_gru_import(self): - # make sure that this somewhat magic import works - from gnuradio import gru - - -if __name__ == '__main__': - gr_unittest.run(test_kludged_imports, "test_kludged_imports.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py deleted file mode 100755 index de1b5aa002..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import tag_utils - -try: - import pmt_swig as pmt -except ImportError: - import pmt - -class test_tag_utils (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - - def tearDown (self): - self.tb = None - - def test_001(self): - t = gr.gr_tag_t() - t.offset = 10 - t.key = pmt.string_to_symbol('key') - t.value = pmt.from_long(23) - t.srcid = pmt.from_bool(False) - pt = tag_utils.tag_to_python(t) - self.assertEqual(pt.key, 'key') - self.assertEqual(pt.value, 23) - self.assertEqual(pt.offset, 10) - - -if __name__ == '__main__': - print 'hi' - gr_unittest.run(test_tag_utils, "test_tag_utils.xml") - diff --git a/gnuradio-core/src/python/gnuradio/gr/tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py deleted file mode 100644 index 923718fc98..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/tag_utils.py +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2003-2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# -""" Conversion tools between stream tags and Python objects """ - -try: import pmt -except: from gruel import pmt - -from gnuradio_core import gr_tag_t - -class PythonTag(object): - " Python container for tags " - def __init__(self): - self.offset = None - self.key = None - self.value = None - self.srcid = None - -def tag_to_python(tag): - """ Convert a stream tag to a Python-readable object """ - newtag = PythonTag() - newtag.offset = tag.offset - newtag.key = pmt.to_python(tag.key) - newtag.value = pmt.to_python(tag.value) - newtag.srcid = pmt.to_python(tag.srcid) - return newtag - -def tag_to_pmt(tag): - """ Convert a Python-readable object to a stream tag """ - newtag = gr_tag_t() - newtag.offset = tag.offset - newtag.key = pmt.to_python(tag.key) - newtag.value = pmt.from_python(tag.value) - newtag.srcid = pmt.from_python(tag.srcid) - return newtag - - diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py deleted file mode 100644 index 947e46bc55..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/top_block.py +++ /dev/null @@ -1,171 +0,0 @@ -# -# Copyright 2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio_core import top_block_swig, \ - top_block_wait_unlocked, top_block_run_unlocked - -#import gnuradio.gr.gr_threading as _threading -import gr_threading as _threading - - -# -# There is no problem that can't be solved with an additional -# level of indirection... -# -# This kludge allows ^C to interrupt top_block.run and top_block.wait -# -# The problem that we are working around is that Python only services -# signals (e.g., KeyboardInterrupt) in its main thread. If the main -# thread is blocked in our C++ version of wait, even though Python's -# SIGINT handler fires, and even though there may be other python -# threads running, no one will know. Thus instead of directly waiting -# in the thread that calls wait (which is likely to be the Python main -# thread), we create a separate thread that does the blocking wait, -# and then use the thread that called wait to do a slow poll of an -# event queue. That thread, which is executing "wait" below is -# interruptable, and if it sees a KeyboardInterrupt, executes a stop -# on the top_block, then goes back to waiting for it to complete. -# This ensures that the unlocked wait that was in progress (in the -# _top_block_waiter thread) can complete, release its mutex and back -# out. If we don't do that, we are never able to clean up, and nasty -# things occur like leaving the USRP transmitter sending a carrier. -# -# See also top_block.wait (below), which uses this class to implement -# the interruptable wait. -# -class _top_block_waiter(_threading.Thread): - def __init__(self, tb): - _threading.Thread.__init__(self) - self.setDaemon(1) - self.tb = tb - self.event = _threading.Event() - self.start() - - def run(self): - top_block_wait_unlocked(self.tb) - self.event.set() - - def wait(self): - try: - while not self.event.isSet(): - self.event.wait(0.100) - except KeyboardInterrupt: - self.tb.stop() - self.wait() - - -# -# This hack forces a 'has-a' relationship to look like an 'is-a' one. -# -# It allows Python classes to subclass this one, while passing through -# method calls to the C++ class shared pointer from SWIG. -# -# It also allows us to intercept method calls if needed. -# -# This allows the 'run_locked' methods, which are defined in gr_top_block.i, -# to release the Python global interpreter lock before calling the actual -# method in gr_top_block -# -class top_block(object): - """ - Top-level hierarchical block representing a flow-graph. - - This is a python wrapper around the C++ implementation to allow - python subclassing. - """ - def __init__(self, name="top_block"): - self._tb = top_block_swig(name) - - def __getattr__(self, name): - if not hasattr(self, "_tb"): - raise RuntimeError("top_block: invalid state--did you forget to call gr.top_block.__init__ in a derived class?") - return getattr(self._tb, name) - - def start(self, max_noutput_items=10000000): - self._tb.start(max_noutput_items) - - def stop(self): - self._tb.stop() - - def run(self, max_noutput_items=10000000): - self.start(max_noutput_items) - self.wait() - - def wait(self): - _top_block_waiter(self._tb).wait() - - - # FIXME: these are duplicated from hier_block2.py; they should really be implemented - # in the original C++ class (gr_hier_block2), then they would all be inherited here - - def connect(self, *points): - '''connect requires one or more arguments that can be coerced to endpoints. - If more than two arguments are provided, they are connected together successively. - ''' - if len (points) < 1: - raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),)) - else: - if len(points) == 1: - self._tb.primitive_connect(points[0].to_basic_block()) - else: - for i in range (1, len (points)): - self._connect(points[i-1], points[i]) - - def msg_connect(self, src, srcport, dst, dstport): - self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); - - def msg_disconnect(self, src, srcport, dst, dstport): - self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); - - def _connect(self, src, dst): - (src_block, src_port) = self._coerce_endpoint(src) - (dst_block, dst_port) = self._coerce_endpoint(dst) - self._tb.primitive_connect(src_block.to_basic_block(), src_port, - dst_block.to_basic_block(), dst_port) - - def _coerce_endpoint(self, endp): - if hasattr(endp, 'to_basic_block'): - return (endp, 0) - else: - if hasattr(endp, "__getitem__") and len(endp) == 2: - return endp # Assume user put (block, port) - else: - raise ValueError("unable to coerce endpoint") - - def disconnect(self, *points): - '''disconnect requires one or more arguments that can be coerced to endpoints. - If more than two arguments are provided, they are disconnected successively. - ''' - if len (points) < 1: - raise ValueError, ("disconnect requires at least one endpoint; %d provided." % (len (points),)) - else: - if len(points) == 1: - self._tb.primitive_disconnect(points[0].to_basic_block()) - else: - for i in range (1, len (points)): - self._disconnect(points[i-1], points[i]) - - def _disconnect(self, src, dst): - (src_block, src_port) = self._coerce_endpoint(src) - (dst_block, dst_port) = self._coerce_endpoint(dst) - self._tb.primitive_disconnect(src_block.to_basic_block(), src_port, - dst_block.to_basic_block(), dst_port) - diff --git a/gnuradio-core/src/python/gnuradio/gr_unittest.py b/gnuradio-core/src/python/gnuradio/gr_unittest.py deleted file mode 100755 index c729566e88..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr_unittest.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# -""" -GNU radio specific extension of unittest. -""" - -import unittest -import gr_xmlrunner -import sys, os, stat - -class TestCase(unittest.TestCase): - """A subclass of unittest.TestCase that adds additional assertions - - Adds new methods assertComplexAlmostEqual, - assertComplexTuplesAlmostEqual and assertFloatTuplesAlmostEqual - """ - - def assertComplexAlmostEqual (self, first, second, places=7, msg=None): - """Fail if the two complex objects are unequal as determined by their - difference rounded to the given number of decimal places - (default 7) and comparing to zero. - - Note that decimal places (from zero) is usually not the same - as significant digits (measured from the most signficant digit). - """ - if round(second.real-first.real, places) != 0: - raise self.failureException, \ - (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) - if round(second.imag-first.imag, places) != 0: - raise self.failureException, \ - (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) - - def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): - """ - Fail if the two complex objects are unequal as determined by... - """ - if abs(ref - x) < abs_eps: - return - - if abs(ref) > abs_eps: - if abs(ref-x)/abs(ref) > rel_eps: - raise self.failureException, \ - (msg or '%s != %s rel_error = %s rel_limit = %s' % ( - `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) - else: - raise self.failureException, \ - (msg or '%s != %s rel_error = %s rel_limit = %s' % ( - `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) - - - - def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None): - self.assertEqual (len(a), len(b)) - for i in xrange (len(a)): - self.assertComplexAlmostEqual (a[i], b[i], places, msg) - - def assertComplexTuplesAlmostEqual2 (self, ref, x, - abs_eps=1e-12, rel_eps=1e-6, msg=None): - self.assertEqual (len(ref), len(x)) - for i in xrange (len(ref)): - try: - self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) - except self.failureException, e: - #sys.stderr.write("index = %d " % (i,)) - #sys.stderr.write("%s\n" % (e,)) - raise - - def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None): - self.assertEqual (len(a), len(b)) - for i in xrange (len(a)): - self.assertAlmostEqual (a[i], b[i], places, msg) - - - def assertFloatTuplesAlmostEqual2 (self, ref, x, - abs_eps=1e-12, rel_eps=1e-6, msg=None): - self.assertEqual (len(ref), len(x)) - for i in xrange (len(ref)): - try: - self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) - except self.failureException, e: - #sys.stderr.write("index = %d " % (i,)) - #sys.stderr.write("%s\n" % (e,)) - raise - - -TestResult = unittest.TestResult -TestSuite = unittest.TestSuite -FunctionTestCase = unittest.FunctionTestCase -TestLoader = unittest.TestLoader -TextTestRunner = unittest.TextTestRunner -TestProgram = unittest.TestProgram -main = TestProgram - -def run(PUT, filename=None): - ''' - Runs the unittest on a TestCase and produces an optional XML report - PUT: the program under test and should be a gr_unittest.TestCase - filename: an optional filename to save the XML report of the tests - this will live in ./.unittests/python - ''' - - # Run this is given a file name - if(filename is not None): - basepath = "./.unittests" - path = basepath + "/python" - - if not os.path.exists(basepath): - os.makedirs(basepath, 0750) - - xmlrunner = None - # only proceed if .unittests is writable - st = os.stat(basepath)[stat.ST_MODE] - if(st & stat.S_IWUSR > 0): - # Test if path exists; if not, build it - if not os.path.exists(path): - os.makedirs(path, 0750) - - # Just for safety: make sure we can write here, too - st = os.stat(path)[stat.ST_MODE] - if(st & stat.S_IWUSR > 0): - # Create an XML runner to filename - fout = file(path+"/"+filename, "w") - xmlrunner = gr_xmlrunner.XMLTestRunner(fout) - - txtrunner = TextTestRunner(verbosity=1) - - # Run the test; runner also creates XML output file - # FIXME: make xmlrunner output to screen so we don't have to do run and main - suite = TestLoader().loadTestsFromTestCase(PUT) - - # use the xmlrunner if we can write the the directory - if(xmlrunner is not None): - xmlrunner.run(suite) - - main() - - # This will run and fail make check if problem - # but does not output to screen. - #main(testRunner = xmlrunner) - - else: - # If no filename is given, just run the test - main() - - -############################################################################## -# Executing this module from the command line -############################################################################## - -if __name__ == "__main__": - main(module=None) diff --git a/gnuradio-core/src/python/gnuradio/gr_xmlrunner.py b/gnuradio-core/src/python/gnuradio/gr_xmlrunner.py deleted file mode 100644 index 31298197ff..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr_xmlrunner.py +++ /dev/null @@ -1,387 +0,0 @@ -""" -XML Test Runner for PyUnit -""" - -# Written by Sebastian Rittau <srittau@jroger.in-berlin.de> and placed in -# the Public Domain. With contributions by Paolo Borelli and others. -# Added to GNU Radio Oct. 3, 2010 - -__version__ = "0.1" - -import os.path -import re -import sys -import time -import traceback -import unittest -from xml.sax.saxutils import escape - -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - - -class _TestInfo(object): - - """Information about a particular test. - - Used by _XMLTestResult. - - """ - - def __init__(self, test, time): - (self._class, self._method) = test.id().rsplit(".", 1) - self._time = time - self._error = None - self._failure = None - - @staticmethod - def create_success(test, time): - """Create a _TestInfo instance for a successful test.""" - return _TestInfo(test, time) - - @staticmethod - def create_failure(test, time, failure): - """Create a _TestInfo instance for a failed test.""" - info = _TestInfo(test, time) - info._failure = failure - return info - - @staticmethod - def create_error(test, time, error): - """Create a _TestInfo instance for an erroneous test.""" - info = _TestInfo(test, time) - info._error = error - return info - - def print_report(self, stream): - """Print information about this test case in XML format to the - supplied stream. - - """ - stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \ - { - "class": self._class, - "method": self._method, - "time": self._time, - }) - if self._failure is not None: - self._print_error(stream, 'failure', self._failure) - if self._error is not None: - self._print_error(stream, 'error', self._error) - stream.write('</testcase>\n') - - def _print_error(self, stream, tagname, error): - """Print information from a failure or error to the supplied stream.""" - text = escape(str(error[1])) - stream.write('\n') - stream.write(' <%s type="%s">%s\n' \ - % (tagname, _clsname(error[0]), text)) - tb_stream = StringIO() - traceback.print_tb(error[2], None, tb_stream) - stream.write(escape(tb_stream.getvalue())) - stream.write(' </%s>\n' % tagname) - stream.write(' ') - - -def _clsname(cls): - return cls.__module__ + "." + cls.__name__ - - -class _XMLTestResult(unittest.TestResult): - - """A test result class that stores result as XML. - - Used by XMLTestRunner. - - """ - - def __init__(self, classname): - unittest.TestResult.__init__(self) - self._test_name = classname - self._start_time = None - self._tests = [] - self._error = None - self._failure = None - - def startTest(self, test): - unittest.TestResult.startTest(self, test) - self._error = None - self._failure = None - self._start_time = time.time() - - def stopTest(self, test): - time_taken = time.time() - self._start_time - unittest.TestResult.stopTest(self, test) - if self._error: - info = _TestInfo.create_error(test, time_taken, self._error) - elif self._failure: - info = _TestInfo.create_failure(test, time_taken, self._failure) - else: - info = _TestInfo.create_success(test, time_taken) - self._tests.append(info) - - def addError(self, test, err): - unittest.TestResult.addError(self, test, err) - self._error = err - - def addFailure(self, test, err): - unittest.TestResult.addFailure(self, test, err) - self._failure = err - - def print_report(self, stream, time_taken, out, err): - """Prints the XML report to the supplied stream. - - The time the tests took to perform as well as the captured standard - output and standard error streams must be passed in.a - - """ - stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \ - { "e": len(self.errors), "f": len(self.failures) }) - stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \ - { - "n": self._test_name, - "t": self.testsRun, - "time": time_taken, - }) - for info in self._tests: - info.print_report(stream) - stream.write(' <system-out><![CDATA[%s]]></system-out>\n' % out) - stream.write(' <system-err><![CDATA[%s]]></system-err>\n' % err) - stream.write('</testsuite>\n') - - -class XMLTestRunner(object): - - """A test runner that stores results in XML format compatible with JUnit. - - XMLTestRunner(stream=None) -> XML test runner - - The XML file is written to the supplied stream. If stream is None, the - results are stored in a file called TEST-<module>.<class>.xml in the - current working directory (if not overridden with the path property), - where <module> and <class> are the module and class name of the test class. - - """ - - def __init__(self, stream=None): - self._stream = stream - self._path = "." - - def run(self, test): - """Run the given test case or test suite.""" - class_ = test.__class__ - classname = class_.__module__ + "." + class_.__name__ - if self._stream == None: - filename = "TEST-%s.xml" % classname - stream = file(os.path.join(self._path, filename), "w") - stream.write('<?xml version="1.0" encoding="utf-8"?>\n') - else: - stream = self._stream - - result = _XMLTestResult(classname) - start_time = time.time() - - fss = _fake_std_streams() - fss.__enter__() - try: - test(result) - try: - out_s = sys.stdout.getvalue() - except AttributeError: - out_s = "" - try: - err_s = sys.stderr.getvalue() - except AttributeError: - err_s = "" - finally: - fss.__exit__(None, None, None) - - time_taken = time.time() - start_time - result.print_report(stream, time_taken, out_s, err_s) - if self._stream is None: - stream.close() - - return result - - def _set_path(self, path): - self._path = path - - path = property(lambda self: self._path, _set_path, None, - """The path where the XML files are stored. - - This property is ignored when the XML file is written to a file - stream.""") - - -class _fake_std_streams(object): - - def __enter__(self): - self._orig_stdout = sys.stdout - self._orig_stderr = sys.stderr - #sys.stdout = StringIO() - #sys.stderr = StringIO() - - def __exit__(self, exc_type, exc_val, exc_tb): - sys.stdout = self._orig_stdout - sys.stderr = self._orig_stderr - - -class XMLTestRunnerTest(unittest.TestCase): - - def setUp(self): - self._stream = StringIO() - - def _try_test_run(self, test_class, expected): - - """Run the test suite against the supplied test class and compare the - XML result against the expected XML string. Fail if the expected - string doesn't match the actual string. All time attributes in the - expected string should have the value "0.000". All error and failure - messages are reduced to "Foobar". - - """ - - runner = XMLTestRunner(self._stream) - runner.run(unittest.makeSuite(test_class)) - - got = self._stream.getvalue() - # Replace all time="X.YYY" attributes by time="0.000" to enable a - # simple string comparison. - got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got) - # Likewise, replace all failure and error messages by a simple "Foobar" - # string. - got = re.sub(r'(?s)<failure (.*?)>.*?</failure>', r'<failure \1>Foobar</failure>', got) - got = re.sub(r'(?s)<error (.*?)>.*?</error>', r'<error \1>Foobar</error>', got) - # And finally Python 3 compatibility. - got = got.replace('type="builtins.', 'type="exceptions.') - - self.assertEqual(expected, got) - - def test_no_tests(self): - """Regression test: Check whether a test run without any tests - matches a previous run. - - """ - class TestTest(unittest.TestCase): - pass - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="0" time="0.000"> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_success(self): - """Regression test: Check whether a test run with a successful test - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - pass - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_failure(self): - """Regression test: Check whether a test run with a failing test - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - self.assert_(False) - self._try_test_run(TestTest, """<testsuite errors="0" failures="1" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> - <failure type="exceptions.AssertionError">Foobar</failure> - </testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_error(self): - """Regression test: Check whether a test run with a erroneous test - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - raise IndexError() - self._try_test_run(TestTest, """<testsuite errors="1" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> - <error type="exceptions.IndexError">Foobar</error> - </testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_stdout_capture(self): - """Regression test: Check whether a test run with output to stdout - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stdout.write("Test\n") - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> - <system-out><![CDATA[Test -]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_stderr_capture(self): - """Regression test: Check whether a test run with output to stderr - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stderr.write("Test\n") - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[Test -]]></system-err> -</testsuite> -""") - - class NullStream(object): - """A file-like object that discards everything written to it.""" - def write(self, buffer): - pass - - def test_unittests_changing_stdout(self): - """Check whether the XMLTestRunner recovers gracefully from unit tests - that change stdout, but don't change it back properly. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stdout = XMLTestRunnerTest.NullStream() - - runner = XMLTestRunner(self._stream) - runner.run(unittest.makeSuite(TestTest)) - - def test_unittests_changing_stderr(self): - """Check whether the XMLTestRunner recovers gracefully from unit tests - that change stderr, but don't change it back properly. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stderr = XMLTestRunnerTest.NullStream() - - runner = XMLTestRunner(self._stream) - runner.run(unittest.makeSuite(TestTest)) - - -if __name__ == "__main__": - unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gru/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gru/CMakeLists.txt deleted file mode 100644 index 1c50989d96..0000000000 --- a/gnuradio-core/src/python/gnuradio/gru/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -include(GrPython) - -GR_PYTHON_INSTALL( - FILES __init__.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/gru - COMPONENT "core_python" -) diff --git a/gnuradio-core/src/python/gnuradio/gru/__init__.py b/gnuradio-core/src/python/gnuradio/gru/__init__.py deleted file mode 100644 index c24439ff54..0000000000 --- a/gnuradio-core/src/python/gnuradio/gru/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import glob -import os.path - -# Semi-hideous kludge to import everything in the gruimpl directory -# into the gnuradio.gru namespace. This keeps us from having to remember -# to manually update this file. - -for p in __path__: - filenames = glob.glob (os.path.join (p, "..", "gruimpl", "*.py")) - for f in filenames: - f = os.path.basename(f).lower() - f = f[:-3] - if f == '__init__': - continue - # print f - exec "from gnuradio.gruimpl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt deleted file mode 100644 index d77da24073..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -include(GrPython) - -GR_PYTHON_INSTALL(FILES - __init__.py - freqz.py - gnuplot_freqz.py - hexint.py - listmisc.py - mathmisc.py - msgq_runner.py - os_read_exactly.py - seq_with_cursor.py - socket_stuff.py - daemon.py - DESTINATION ${GR_PYTHON_DIR}/gnuradio/gruimpl - COMPONENT "core_python" -) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py deleted file mode 100644 index a4917cf64c..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# make this a package diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/daemon.py b/gnuradio-core/src/python/gnuradio/gruimpl/daemon.py deleted file mode 100644 index e04702152d..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/daemon.py +++ /dev/null @@ -1,102 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# -import os, sys, signal - -# Turn application into a background daemon process. -# -# When this function returns: -# -# 1) The calling process is disconnected from its controlling terminal -# and will not exit when the controlling session exits -# 2) If a pidfile name is provided, it is created and the new pid is -# written into it. -# 3) If a logfile name is provided, it is opened and stdout/stderr are -# redirected to it. -# 4) The process current working directory is changed to '/' to avoid -# pinning any filesystem mounts. -# 5) The process umask is set to 0111. -# -# The return value is the new pid. -# -# To create GNU Radio applications that operate as daemons, add a call to this -# function after all initialization but just before calling gr.top_block.run() -# or .start(). -# -# Daemonized GNU Radio applications may be stopped by sending them a -# SIGINT, SIGKILL, or SIGTERM, e.g., using 'kill pid' from the command line. -# -# If your application uses gr.top_block.run(), the flowgraph will be stopped -# and the function will return. You should allow your daemon program to exit -# at this point. -# -# If your application uses gr.top_block.start(), you are responsible for hooking -# the Python signal handler (see 'signal' module) and calling gr.top_block.stop() -# on your top block, and otherwise causing your daemon process to exit. -# - -def daemonize(pidfile=None, logfile=None): - # fork() into background - try: - pid = os.fork() - except OSError, e: - raise Exception, "%s [%d]" % (e.strerror, e.errno) - - if pid == 0: # First child of first fork() - # Become session leader of new session - os.setsid() - - # fork() into background again - try: - pid = os.fork() - except OSError, e: - raise Exception, "%s [%d]" % (e.strerror, e.errno) - - if pid != 0: - os._exit(0) # Second child of second fork() - - else: # Second child of first fork() - os._exit(0) - - os.umask(0111) - - # Write pid - pid = os.getpid() - if pidfile is not None: - open(pidfile, 'w').write('%d\n'%pid) - - # Redirect streams - if logfile is not None: - lf = open(logfile, 'a+') - sys.stdout = lf - sys.stderr = lf - - # Prevent pinning any filesystem mounts - os.chdir('/') - - # Tell caller what pid to send future signals to - return pid - -if __name__ == "__main__": - import time - daemonize() - print "Hello, world, from daemon process." - time.sleep(20) - print "Goodbye, world, from daemon process." diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py deleted file mode 100644 index 60dca64a58..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py +++ /dev/null @@ -1,344 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# This code lifted from various parts of www.scipy.org -eb 2005-01-24 - -# Copyright (c) 2001, 2002 Enthought, Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# a. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# b. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# c. Neither the name of the Enthought nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -# DAMAGE. -# - -__all__ = ['freqz'] - -import numpy -from numpy import * -Num=numpy - -def atleast_1d(*arys): - """ Force a sequence of arrays to each be at least 1D. - - Description: - Force an array to be at least 1D. If an array is 0D, the - array is converted to a single row of values. Otherwise, - the array is unaltered. - Arguments: - *arys -- arrays to be converted to 1 or more dimensional array. - Returns: - input array converted to at least 1D array. - """ - res = [] - for ary in arys: - ary = asarray(ary) - if len(ary.shape) == 0: - result = numpy.array([ary[0]]) - else: - result = ary - res.append(result) - if len(res) == 1: - return res[0] - else: - return res - - -def polyval(p,x): - """Evaluate the polynomial p at x. If x is a polynomial then composition. - - Description: - - If p is of length N, this function returns the value: - p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1] - - x can be a sequence and p(x) will be returned for all elements of x. - or x can be another polynomial and the composite polynomial p(x) will be - returned. - """ - p = asarray(p) - if isinstance(x,poly1d): - y = 0 - else: - x = asarray(x) - y = numpy.zeros(x.shape,x.typecode()) - for i in range(len(p)): - y = x * y + p[i] - return y - -class poly1d: - """A one-dimensional polynomial class. - - p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3 - - p(0.5) evaluates the polynomial at the location - p.r is a list of roots - p.c is the coefficient array [1,2,3] - p.order is the polynomial order (after leading zeros in p.c are removed) - p[k] is the coefficient on the kth power of x (backwards from - sequencing the coefficient array. - - polynomials can be added, substracted, multplied and divided (returns - quotient and remainder). - asarray(p) will also give the coefficient array, so polynomials can - be used in all functions that accept arrays. - """ - def __init__(self, c_or_r, r=0): - if isinstance(c_or_r,poly1d): - for key in c_or_r.__dict__.keys(): - self.__dict__[key] = c_or_r.__dict__[key] - return - if r: - c_or_r = poly(c_or_r) - c_or_r = atleast_1d(c_or_r) - if len(c_or_r.shape) > 1: - raise ValueError, "Polynomial must be 1d only." - c_or_r = trim_zeros(c_or_r, trim='f') - if len(c_or_r) == 0: - c_or_r = numpy.array([0]) - self.__dict__['coeffs'] = c_or_r - self.__dict__['order'] = len(c_or_r) - 1 - - def __array__(self,t=None): - if t: - return asarray(self.coeffs,t) - else: - return asarray(self.coeffs) - - def __coerce__(self,other): - return None - - def __repr__(self): - vals = repr(self.coeffs) - vals = vals[6:-1] - return "poly1d(%s)" % vals - - def __len__(self): - return self.order - - def __str__(self): - N = self.order - thestr = "0" - for k in range(len(self.coeffs)): - coefstr ='%.4g' % abs(self.coeffs[k]) - if coefstr[-4:] == '0000': - coefstr = coefstr[:-5] - power = (N-k) - if power == 0: - if coefstr != '0': - newstr = '%s' % (coefstr,) - else: - if k == 0: - newstr = '0' - else: - newstr = '' - elif power == 1: - if coefstr == '0': - newstr = '' - elif coefstr == '1': - newstr = 'x' - else: - newstr = '%s x' % (coefstr,) - else: - if coefstr == '0': - newstr = '' - elif coefstr == '1': - newstr = 'x**%d' % (power,) - else: - newstr = '%s x**%d' % (coefstr, power) - - if k > 0: - if newstr != '': - if self.coeffs[k] < 0: - thestr = "%s - %s" % (thestr, newstr) - else: - thestr = "%s + %s" % (thestr, newstr) - elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0): - thestr = "-%s" % (newstr,) - else: - thestr = newstr - return _raise_power(thestr) - - - def __call__(self, val): - return polyval(self.coeffs, val) - - def __mul__(self, other): - if isscalar(other): - return poly1d(self.coeffs * other) - else: - other = poly1d(other) - return poly1d(polymul(self.coeffs, other.coeffs)) - - def __rmul__(self, other): - if isscalar(other): - return poly1d(other * self.coeffs) - else: - other = poly1d(other) - return poly1d(polymul(self.coeffs, other.coeffs)) - - def __add__(self, other): - other = poly1d(other) - return poly1d(polyadd(self.coeffs, other.coeffs)) - - def __radd__(self, other): - other = poly1d(other) - return poly1d(polyadd(self.coeffs, other.coeffs)) - - def __pow__(self, val): - if not isscalar(val) or int(val) != val or val < 0: - raise ValueError, "Power to non-negative integers only." - res = [1] - for k in range(val): - res = polymul(self.coeffs, res) - return poly1d(res) - - def __sub__(self, other): - other = poly1d(other) - return poly1d(polysub(self.coeffs, other.coeffs)) - - def __rsub__(self, other): - other = poly1d(other) - return poly1d(polysub(other.coeffs, self.coeffs)) - - def __div__(self, other): - if isscalar(other): - return poly1d(self.coeffs/other) - else: - other = poly1d(other) - return map(poly1d,polydiv(self.coeffs, other.coeffs)) - - def __rdiv__(self, other): - if isscalar(other): - return poly1d(other/self.coeffs) - else: - other = poly1d(other) - return map(poly1d,polydiv(other.coeffs, self.coeffs)) - - def __setattr__(self, key, val): - raise ValueError, "Attributes cannot be changed this way." - - def __getattr__(self, key): - if key in ['r','roots']: - return roots(self.coeffs) - elif key in ['c','coef','coefficients']: - return self.coeffs - elif key in ['o']: - return self.order - else: - return self.__dict__[key] - - def __getitem__(self, val): - ind = self.order - val - if val > self.order: - return 0 - if val < 0: - return 0 - return self.coeffs[ind] - - def __setitem__(self, key, val): - ind = self.order - key - if key < 0: - raise ValueError, "Does not support negative powers." - if key > self.order: - zr = numpy.zeros(key-self.order,self.coeffs.typecode()) - self.__dict__['coeffs'] = numpy.concatenate((zr,self.coeffs)) - self.__dict__['order'] = key - ind = 0 - self.__dict__['coeffs'][ind] = val - return - - def integ(self, m=1, k=0): - return poly1d(polyint(self.coeffs,m=m,k=k)) - - def deriv(self, m=1): - return poly1d(polyder(self.coeffs,m=m)) - -def freqz(b, a, worN=None, whole=0, plot=None): - """Compute frequency response of a digital filter. - - Description: - - Given the numerator (b) and denominator (a) of a digital filter compute - its frequency response. - - jw -jw -jmw - jw B(e) b[0] + b[1]e + .... + b[m]e - H(e) = ---- = ------------------------------------ - jw -jw -jnw - A(e) a[0] + a[2]e + .... + a[n]e - - Inputs: - - b, a --- the numerator and denominator of a linear filter. - worN --- If None, then compute at 512 frequencies around the unit circle. - If a single integer, the compute at that many frequencies. - Otherwise, compute the response at frequencies given in worN - whole -- Normally, frequencies are computed from 0 to pi (upper-half of - unit-circle. If whole is non-zero compute frequencies from 0 - to 2*pi. - - Outputs: (h,w) - - h -- The frequency response. - w -- The frequencies at which h was computed. - """ - b, a = map(atleast_1d, (b,a)) - if whole: - lastpoint = 2*pi - else: - lastpoint = pi - if worN is None: - N = 512 - w = Num.arange(0,lastpoint,lastpoint/N) - elif isinstance(worN, types.IntType): - N = worN - w = Num.arange(0,lastpoint,lastpoint/N) - else: - w = worN - w = atleast_1d(w) - zm1 = exp(-1j*w) - h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1) - # if not plot is None: - # plot(w, h) - return h, w diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py deleted file mode 100755 index 18dcbec3eb..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -__all__ = ['gnuplot_freqz'] - -import tempfile -import os -import math -import numpy - -from gnuradio import gr -from gnuradio.gruimpl.freqz import freqz - - -def gnuplot_freqz (hw, Fs=None, logfreq=False): - - """hw is a tuple of the form (h, w) where h is sequence of complex - freq responses, and w is a sequence of corresponding frequency - points. Plot the frequency response using gnuplot. If Fs is - provide, use it as the sampling frequency, else use 2*pi. - - Returns a handle to the gnuplot graph. When the handle is reclaimed - the graph is torn down.""" - - data_file = tempfile.NamedTemporaryFile () - cmd_file = os.popen ('gnuplot', 'w') - - h, w = hw - ampl = 20 * numpy.log10 (numpy.absolute (h) + 1e-9) - phase = map (lambda x: math.atan2 (x.imag, x.real), h) - - if Fs: - w *= (Fs/(2*math.pi)) - - for freq, a, ph in zip (w, ampl, phase): - data_file.write ("%g\t%g\t%g\n" % (freq, a, ph)) - - data_file.flush () - - cmd_file.write ("set grid\n") - if logfreq: - cmd_file.write ("set logscale x\n") - else: - cmd_file.write ("unset logscale x\n") - cmd_file.write ("plot '%s' using 1:2 with lines\n" % (data_file.name,)) - cmd_file.flush () - - return (cmd_file, data_file) - - -def test_plot (): - sample_rate = 2.0e6 - #taps = firdes.low_pass(1, sample_rate, 200000, 100000, firdes.WIN_HAMMING) - taps = (0.0007329441141337156, 0.0007755281985737383, 0.0005323155201040208, - -7.679847761841656e-19, -0.0007277769618667662, -0.001415981911122799, - -0.0017135187517851591, -0.001282231998629868, 1.61239866282397e-18, - 0.0018589380197227001, 0.0035909228026866913, 0.004260237794369459, - 0.00310456077568233, -3.0331308923229716e-18, -0.004244099836796522, - -0.007970594801008701, -0.009214458055794239, -0.006562007591128349, - 4.714311174044374e-18, 0.008654761128127575, 0.01605774275958538, - 0.01841980405151844, 0.013079923577606678, -6.2821650235090215e-18, - -0.017465557903051376, -0.032989680767059326, -0.03894065320491791, - -0.028868533670902252, 7.388111706347014e-18, 0.04517475143074989, - 0.09890196472406387, 0.14991308748722076, 0.18646684288978577, - 0.19974154233932495, 0.18646684288978577, 0.14991308748722076, - 0.09890196472406387, 0.04517475143074989, 7.388111706347014e-18, - -0.028868533670902252, -0.03894065320491791, -0.032989680767059326, - -0.017465557903051376, -6.2821650235090215e-18, 0.013079923577606678, - 0.01841980405151844, 0.01605774275958538, 0.008654761128127575, - 4.714311174044374e-18, -0.006562007591128349, -0.009214458055794239, - -0.007970594801008701, -0.004244099836796522, -3.0331308923229716e-18, - 0.00310456077568233, 0.004260237794369459, 0.0035909228026866913, - 0.0018589380197227001, 1.61239866282397e-18, -0.001282231998629868, - -0.0017135187517851591, -0.001415981911122799, -0.0007277769618667662, - -7.679847761841656e-19, 0.0005323155201040208, 0.0007755281985737383, - 0.0007329441141337156) - - # print len (taps) - return gnuplot_freqz (freqz (taps, 1), sample_rate) - -if __name__ == '__main__': - handle = test_plot () - raw_input ('Press Enter to continue: ') diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py deleted file mode 100644 index 0fb5ecde04..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -def hexint(mask): - """ - Convert unsigned masks into signed ints. - - This allows us to use hex constants like 0xf0f0f0f2 when talking to - our hardware and not get screwed by them getting treated as python - longs. - """ - if mask >= 2**31: - return int(mask-2**32) - return mask - -def hexshort(mask): - """ - Convert unsigned masks into signed shorts. - - This allows us to use hex constants like 0x8000 when talking to - our hardware and not get screwed by them getting treated as python - longs. - """ - if mask >= 2**15: - return int(mask-2**16) - return mask diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py deleted file mode 100644 index 9e70eb863c..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -def list_reverse(x): - """ - Return a copy of x that is reverse order. - """ - r = list(x) - r.reverse() - return r - diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py deleted file mode 100644 index 7e6f23a346..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import math - -def gcd(a,b): - while b: - a,b = b, a % b - return a - -def lcm(a,b): - return a * b / gcd(a, b) - -def log2(x): - return math.log(x)/math.log(2) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/msgq_runner.py b/gnuradio-core/src/python/gnuradio/gruimpl/msgq_runner.py deleted file mode 100644 index 767a74a717..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/msgq_runner.py +++ /dev/null @@ -1,82 +0,0 @@ -# -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -Convenience class for dequeuing messages from a gr.msg_queue and -invoking a callback. - -Creates a Python thread that does a blocking read on the supplied -gr.msg_queue, then invokes callback each time a msg is received. - -If the msg type is not 0, then it is treated as a signal to exit -its loop. - -If the callback raises an exception, and the runner was created -with 'exit_on_error' equal to True, then the runner will store the -exception and exit its loop, otherwise the exception is ignored. - -To get the exception that the callback raised, if any, call -exit_error() on the object. - -To manually stop the runner, call stop() on the object. - -To determine if the runner has exited, call exited() on the object. -""" - -from gnuradio import gr -import gnuradio.gr.gr_threading as _threading - -class msgq_runner(_threading.Thread): - - def __init__(self, msgq, callback, exit_on_error=False): - _threading.Thread.__init__(self) - - self._msgq = msgq - self._callback = callback - self._exit_on_error = exit_on_error - self._done = False - self._exited = False - self._exit_error = None - self.setDaemon(1) - self.start() - - def run(self): - while not self._done: - msg = self._msgq.delete_head() - if msg.type() != 0: - self.stop() - else: - try: - self._callback(msg) - except Exception, e: - if self._exit_on_error: - self._exit_error = e - self.stop() - self._exited = True - - def stop(self): - self._done = True - - def exited(self): - return self._exited - - def exit_error(self): - return self._exit_error diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py deleted file mode 100644 index 40b053770e..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import os - -def os_read_exactly(file_descriptor, nbytes): - """ - Replacement for os.read that blocks until it reads exactly nbytes. - - """ - s = '' - while nbytes > 0: - sbuf = os.read(file_descriptor, nbytes) - if not(sbuf): - return '' - nbytes -= len(sbuf) - s = s + sbuf - return s diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py deleted file mode 100644 index def3299b69..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py +++ /dev/null @@ -1,77 +0,0 @@ -# -# Copyright 2003,2004 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# misc utilities - -import types -import exceptions - -class seq_with_cursor (object): - __slots__ = [ 'items', 'index' ] - - def __init__ (self, items, initial_index = None, initial_value = None): - assert len (items) > 0, "seq_with_cursor: len (items) == 0" - self.items = items - self.set_index (initial_index) - if initial_value is not None: - self.set_index_by_value(initial_value) - - def set_index (self, initial_index): - if initial_index is None: - self.index = len (self.items) / 2 - elif initial_index >= 0 and initial_index < len (self.items): - self.index = initial_index - else: - raise exceptions.ValueError - - def set_index_by_value(self, v): - """ - Set index to the smallest value such that items[index] >= v. - If there is no such item, set index to the maximum value. - """ - self.set_index(0) # side effect! - cv = self.current() - more = True - while cv < v and more: - cv, more = self.next() # side effect! - - def next (self): - new_index = self.index + 1 - if new_index < len (self.items): - self.index = new_index - return self.items[new_index], True - else: - return self.items[self.index], False - - def prev (self): - new_index = self.index - 1 - if new_index >= 0: - self.index = new_index - return self.items[new_index], True - else: - return self.items[self.index], False - - def current (self): - return self.items[self.index] - - def get_seq (self): - return self.items[:] # copy of items - diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py deleted file mode 100644 index 489b6ab255..0000000000 --- a/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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; either version 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# random socket related stuff - -import socket -import os -import sys - -def tcp_connect_or_die(sock_addr): - """ - - Args: - sock_addr: (host, port) to connect to (tuple) - - Returns: - : socket or exits - """ - s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) - try: - s.connect(sock_addr) - except socket.error, err: - sys.stderr.write('Failed to connect to %s: %s\n' % - (sock_addr, os.strerror (err.args[0]),)) - sys.exit(1) - return s - -def udp_connect_or_die(sock_addr): - """ - - Args: - sock_addr: (host, port) to connect to (tuple) - - Returns: - : socket or exits - """ - s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) - try: - s.connect(sock_addr) - except socket.error, err: - sys.stderr.write('Failed to connect to %s: %s\n' % - (sock_addr, os.strerror (err.args[0]),)) - sys.exit(1) - return s |