summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/doxygen/other/logger.dox18
-rw-r--r--gnuradio-runtime/include/gnuradio/py_feval.h1
-rw-r--r--gnuradio-runtime/include/gnuradio/sys_pri.h10
-rw-r--r--gnuradio-runtime/include/gnuradio/xoroshiro128p.h103
-rw-r--r--gnuradio-runtime/lib/math/random.cc18
-rw-r--r--gnuradio-runtime/lib/pmt/pmt.cc8
-rw-r--r--gnuradio-runtime/python/gnuradio/eng_notation.py23
-rw-r--r--gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t3
-rw-r--r--gr-analog/lib/fastnoise_source_X_impl.cc.t34
-rw-r--r--gr-analog/lib/fastnoise_source_X_impl.h.t2
-rw-r--r--gr-analog/python/analog/qa_fastnoise.py120
-rw-r--r--gr-blocks/lib/ConfigChecks.cmake7
-rw-r--r--gr-blocks/lib/test_tag_variable_rate_ff_impl.cc20
-rw-r--r--gr-blocks/lib/test_tag_variable_rate_ff_impl.h1
-rw-r--r--gr-channels/lib/selective_fading_model_impl.cc2
-rw-r--r--gr-digital/lib/chunks_to_symbols_XX_impl.cc.t30
-rw-r--r--gr-filter/grc/filter_pfb_channelizer.xml2
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_arb_resampler.h4
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_arb_resampler_fff.h2
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h18
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h8
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_interpolator_ccf.h6
-rw-r--r--gr-filter/include/gnuradio/filter/polyphase_filterbank.h12
-rw-r--r--gr-qtgui/grc/qtgui_ber_sink_b.xml2
-rw-r--r--gr-qtgui/grc/qtgui_check_box.xml3
-rw-r--r--gr-qtgui/grc/qtgui_chooser.xml3
-rw-r--r--gr-qtgui/grc/qtgui_const_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_edit_box_msg.xml2
-rw-r--r--gr-qtgui/grc/qtgui_entry.xml5
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_histogram_sink_x.xml4
-rw-r--r--gr-qtgui/grc/qtgui_label.xml3
-rw-r--r--gr-qtgui/grc/qtgui_number_sink.xml3
-rw-r--r--gr-qtgui/grc/qtgui_push_button.xml4
-rw-r--r--gr-qtgui/grc/qtgui_range.xml3
-rw-r--r--gr-qtgui/grc/qtgui_sink_x.xml2
-rw-r--r--gr-qtgui/grc/qtgui_tab_widget.xml3
-rw-r--r--gr-qtgui/grc/qtgui_time_raster_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_time_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_vector_sink_f.xml3
-rw-r--r--gr-qtgui/grc/qtgui_waterfall_sink_x.xml3
-rw-r--r--grc/core/Param.py152
-rw-r--r--grc/core/generator/Generator.py2
-rw-r--r--grc/gui/BlockTreeWindow.py3
44 files changed, 477 insertions, 187 deletions
diff --git a/docs/doxygen/other/logger.dox b/docs/doxygen/other/logger.dox
index ae6a744d00..c8e4a5daa2 100644
--- a/docs/doxygen/other/logger.dox
+++ b/docs/doxygen/other/logger.dox
@@ -212,6 +212,24 @@ This creates a pointer called LOG (which is instantiated as a
log4cpp:LoggerPtr in the macro) that we can now use locally as the
input to our logging macros like 'GR_LOG_INFO(LOG, "message")'.
+\subsection using_logging Using Logging in Out of Tree Modules
+
+In order to use the logging interface in an out of tree module based on a
+gr_modtool template module, several CMake modifications are required.
+Without these changes, logging will be disabled.
+
+GrMiscUtils.cmake module must be included in the OOT module top level
+CMakeLists.Texts file, and the GR_LOGGING() function provided by GrMiscUtils
+must be called from the same top level CMakeLists.txt file. This will
+set the appropriate build environment and during that process, attempt
+to find the log4cpp package using the FindLog4Cpp.cmake module.
+This module is not included in the module by gr_modtool, but is part of
+the GNU Radio codebase and can be copied directly into the cmake/Modules/
+directory of the OOT module.
+
+Once these CMake changes are made, the GR logging interface will function
+as documented on this page.
+
\section logPy Logging from Python
The logging capability has been brought out python via swig. The configuration
diff --git a/gnuradio-runtime/include/gnuradio/py_feval.h b/gnuradio-runtime/include/gnuradio/py_feval.h
index cef168c8f0..89491af0b4 100644
--- a/gnuradio-runtime/include/gnuradio/py_feval.h
+++ b/gnuradio-runtime/include/gnuradio/py_feval.h
@@ -23,6 +23,7 @@
#ifndef INCLUDED_GR_PY_FEVAL_H
#define INCLUDED_GR_PY_FEVAL_H
+#include <Python.h>
#include <pmt/pmt.h>
#include <gnuradio/feval.h>
diff --git a/gnuradio-runtime/include/gnuradio/sys_pri.h b/gnuradio-runtime/include/gnuradio/sys_pri.h
index adceb91b9d..d251455a11 100644
--- a/gnuradio-runtime/include/gnuradio/sys_pri.h
+++ b/gnuradio-runtime/include/gnuradio/sys_pri.h
@@ -23,7 +23,7 @@
#define INCLUDED_GNURADIO_SYS_PRI_H
#include <gnuradio/api.h>
-#include <realtime.h>
+#include <gnuradio/realtime.h>
/*
* A single place to define real-time priorities used by the system itself
@@ -31,10 +31,10 @@
namespace gr {
struct GR_RUNTIME_API sys_pri {
- static rt_sched_param python(); // python code
- static rt_sched_param normal(); // normal blocks
- static rt_sched_param gcell_event_handler();
- static rt_sched_param usrp2_backend(); // thread that services the ethernet
+ static struct GR_RUNTIME_API rt_sched_param python(); // python code
+ static struct GR_RUNTIME_API rt_sched_param normal(); // normal blocks
+ static struct GR_RUNTIME_API rt_sched_param gcell_event_handler();
+ static struct GR_RUNTIME_API rt_sched_param usrp2_backend(); // thread that services the ethernet
};
} /* namespace gr */
diff --git a/gnuradio-runtime/include/gnuradio/xoroshiro128p.h b/gnuradio-runtime/include/gnuradio/xoroshiro128p.h
new file mode 100644
index 0000000000..b3e6dcb12d
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/xoroshiro128p.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 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.
+ */
+
+// Built on XOROSHIRO128+ by David Blackman and Sebastiano Vigna who put this
+// under CC-0, colloquially known as "public domain (or as close you get to that
+// in your local legislation)" see
+// http://xoroshiro.di.unimi.it/xoroshiro128plus.c
+// Conversion to a local state (original used global state) done by Marcus
+// Müller, 2018.
+#ifndef INCLUDED_XOROSHIRO128P_H
+#define INCLUDED_XOROSHIRO128P_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/*! \brief rotating left shift helper
+ * According to the original authors, this will on most platforms reduce to a single instruction
+ */
+static inline uint64_t rotl(const uint64_t x, const int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+
+/*! \brief generate the next random number and update the state.
+ * This is the workhorse, here!
+ */
+static inline uint64_t xoroshiro128p_next(uint64_t *state) {
+ const uint64_t s0 = state[0];
+ uint64_t s1 = state[1];
+ const uint64_t result = s0 + s1;
+
+ s1 ^= s0;
+ state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
+ state[1] = rotl(s1, 36); // c
+
+ return result;
+}
+
+
+/*! \brief Advance the internal state by 2^64 steps; useful when coordinating multiple independent RNGs
+ This is the jump function for the generator. It is equivalent
+ to 2^64 calls to next(); it can be used to generate 2^64
+ non-overlapping subsequences for parallel computations. */
+static inline void xoroshiro128p_jump(uint64_t *state) {
+ static const uint64_t JUMP[] = { 0xbeac0467eba5facb, 0xd86b048b86aa9922 };
+
+ uint64_t s0 = 0;
+ uint64_t s1 = 0;
+ for(unsigned int i = 0; i < sizeof (JUMP) / sizeof (*JUMP); ++i) {
+ for(unsigned int b = 0; b < 64; ++b) {
+ if (JUMP[i] & UINT64_C(1) << b) {
+ s0 ^= state[0];
+ s1 ^= state[1];
+ }
+ xoroshiro128p_next(state);
+ }
+ }
+
+ state[0] = s0;
+ state[1] = s1;
+}
+
+/*! \brief step of the SPLITMIX64 RNG; only used internally for seeding
+ * This RNG isn't as good as XOROSHIRO128+, so it's only used to initialize a 128 bit state from a seed.
+ */
+static inline uint64_t splitmix64_next(uint64_t *state) {
+ uint64_t z = (*state += 0x9e3779b97f4a7c15);
+ z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+ z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+ return z ^ (z >> 31);
+}
+
+/*! \brief Seed the 128 bit state from a 64 bit seed
+ */
+static inline void xoroshiro128p_seed(uint64_t *state, const uint64_t seed) {
+ state[0] = seed;
+ state[1] = splitmix64_next(state);
+ xoroshiro128p_jump(state);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif // Include guard
diff --git a/gnuradio-runtime/lib/math/random.cc b/gnuradio-runtime/lib/math/random.cc
index 401ba89735..cedaf4b97f 100644
--- a/gnuradio-runtime/lib/math/random.cc
+++ b/gnuradio-runtime/lib/math/random.cc
@@ -73,9 +73,12 @@ namespace gr {
void
random::reseed(unsigned int seed)
{
- if(seed==0) d_seed = static_cast<unsigned int>(std::time(0));
- else d_seed = seed;
- d_rng->seed(d_seed);
+ d_seed = seed;
+ if (d_seed == 0){
+ d_rng->seed();
+ } else {
+ d_rng->seed(d_seed);
+ }
// reinstantiate generators. Otherwise reseed doesn't take effect.
delete d_generator;
d_generator = new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > (*d_rng,*d_uniform); // create number generator in [0,1) from boost.random
@@ -138,11 +141,12 @@ namespace gr {
float
random::laplacian()
{
- float z = ran1()-0.5;
- if(z>0) return -logf(1-2*z);
- else return logf(1+2*z);
+ float z = ran1();
+ if (z > 0.5f){
+ return -logf(2.0f * (1.0f - z) );
+ }
+ return logf(2 * z);
}
-
/*
* Copied from The KC7WW / OH2BNS Channel Simulator
* FIXME Need to check how good this is at some point
diff --git a/gnuradio-runtime/lib/pmt/pmt.cc b/gnuradio-runtime/lib/pmt/pmt.cc
index 3b92481549..0fe4dbde8e 100644
--- a/gnuradio-runtime/lib/pmt/pmt.cc
+++ b/gnuradio-runtime/lib/pmt/pmt.cc
@@ -1158,12 +1158,12 @@ equal(const pmt_t& x, const pmt_t& y)
return false;
size_t len_x, len_y;
- if (memcmp(xv->uniform_elements(len_x),
- yv->uniform_elements(len_y),
- len_x) == 0)
+ const void *x_m = xv->uniform_elements(len_x);
+ const void *y_m = yv->uniform_elements(len_y);
+ if (memcmp(x_m, y_m, len_x) == 0)
return true;
- return true;
+ return false;
}
// FIXME add other cases here...
diff --git a/gnuradio-runtime/python/gnuradio/eng_notation.py b/gnuradio-runtime/python/gnuradio/eng_notation.py
index d23f9005f0..12332aef7d 100644
--- a/gnuradio-runtime/python/gnuradio/eng_notation.py
+++ b/gnuradio-runtime/python/gnuradio/eng_notation.py
@@ -36,29 +36,30 @@ scale_factor['p'] = 1e-12
scale_factor['f'] = 1e-15
scale_factor['a'] = 1e-18
-def num_to_str (n):
+def num_to_str (n, precision=6):
'''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n'''
m = abs(n)
+ format_spec = '%.' + repr(int(precision)) + 'g'
if m >= 1e9:
- return "%gG" % (n * 1e-9)
+ return '%sG' % float(format_spec % (n * 1e-9))
elif m >= 1e6:
- return "%gM" % (n * 1e-6)
+ return '%sM' % float(format_spec % (n * 1e-6))
elif m >= 1e3:
- return "%gk" % (n * 1e-3)
+ return '%sk' % float(format_spec % (n * 1e-3))
elif m >= 1:
- return "%g" % (n)
+ return '%s' % float(format_spec % (n))
elif m >= 1e-3:
- return "%gm" % (n * 1e3)
+ return '%sm' % float(format_spec % (n * 1e3))
elif m >= 1e-6:
- return "%gu" % (n * 1e6) # where's that mu when you need it (unicode?)
+ return '%su' % float(format_spec % (n * 1e6))
elif m >= 1e-9:
- return "%gn" % (n * 1e9)
+ return '%sn' % float(format_spec % (n * 1e9))
elif m >= 1e-12:
- return "%gp" % (n * 1e12)
+ return '%sp' % float(format_spec % (n * 1e12))
elif m >= 1e-15:
- return "%gf" % (n * 1e15)
+ return '%sf' % float(format_spec % (n * 1e15))
else:
- return "%g" % (n)
+ return '%s' % float(format_spec % (n))
def str_to_num (value):
diff --git a/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t b/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
index 850633979c..f588299604 100644
--- a/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
+++ b/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
@@ -29,6 +29,8 @@
#include <gnuradio/analog/noise_type.h>
#include <gnuradio/sync_block.h>
+#include <vector>
+
namespace gr {
namespace analog {
@@ -62,6 +64,7 @@ namespace gr {
long seed = 0, long samples=1024*16);
virtual @TYPE@ sample() = 0;
virtual @TYPE@ sample_unbiased() = 0;
+ virtual const std::vector<@TYPE@>& samples() const = 0;
/*!
* Set the noise type. Nominally from the
diff --git a/gr-analog/lib/fastnoise_source_X_impl.cc.t b/gr-analog/lib/fastnoise_source_X_impl.cc.t
index 940918b11b..72c6cb0582 100644
--- a/gr-analog/lib/fastnoise_source_X_impl.cc.t
+++ b/gr-analog/lib/fastnoise_source_X_impl.cc.t
@@ -27,6 +27,7 @@
#endif
#include "@IMPL_NAME@.h"
+#include <gnuradio/xoroshiro128p.h>
#include <gnuradio/io_signature.h>
#include <stdexcept>
@@ -46,13 +47,13 @@ namespace gr {
io_signature::make(1, 1, sizeof(@TYPE@))),
d_type(type),
#if @IS_COMPLEX@ // complex?
- d_ampl(ampl/sqrtf(2.0f)),
+ d_ampl(ampl/sqrtf(2.0f))
#else
- d_ampl(ampl),
+ d_ampl(ampl)
#endif
- d_rng(seed)
{
d_samples.resize(samples);
+ xoroshiro128p_seed(d_state, (uint64_t) seed);
generate();
}
@@ -144,32 +145,27 @@ namespace gr {
@TYPE@ @IMPL_NAME@::sample()
{
-#ifdef HAVE_RAND48
- size_t idx = lrand48() % d_samples.size();
-#else
- size_t idx = rand() % d_samples.size();
-#endif
+ size_t idx = xoroshiro128p_next(d_state) % d_samples.size();
return d_samples[idx];
}
-#ifndef FASTNOISE_RANDOM_SIGN
-#ifndef HAVE_RAND48
-#define FASTNOISE_RANDOM_SIGN ((rand()%2==0)?1:-1)
-#else
-#define FASTNOISE_RANDOM_SIGN ((lrand48()%2==0)?1:-1)
-#endif
-#endif
-
@TYPE@ @IMPL_NAME@::sample_unbiased()
{
+ uint64_t random_int = xoroshiro128p_next(d_state);
#if @IS_COMPLEX@
gr_complex s(sample());
- return gr_complex(FASTNOISE_RANDOM_SIGN * s.real(),
- FASTNOISE_RANDOM_SIGN * s.imag());
+ float re = (random_int & (UINT64_C(1)<<23)) ? (- s.real()) : (s.real());
+ float im = (random_int & (UINT64_C(1)<<42)) ? (- s.real()) : (s.real());
+ return gr_complex(re, im);
#else
- return FASTNOISE_RANDOM_SIGN * sample();
+ float s = sample();
+ return (random_int & (1<<23)) ? (-s) : s;
#endif
}
+ const std::vector<@TYPE@>& @IMPL_NAME@::samples() const
+ {
+ return d_samples;
+ }
} /* namespace analog */
} /* namespace gr */
diff --git a/gr-analog/lib/fastnoise_source_X_impl.h.t b/gr-analog/lib/fastnoise_source_X_impl.h.t
index 8ad1e4f8fe..ef0465729d 100644
--- a/gr-analog/lib/fastnoise_source_X_impl.h.t
+++ b/gr-analog/lib/fastnoise_source_X_impl.h.t
@@ -38,6 +38,7 @@ namespace gr {
float d_ampl;
gr::random d_rng;
std::vector<@TYPE@> d_samples;
+ uint64_t d_state[2];
public:
@IMPL_NAME@(noise_type_t type, float ampl, long seed, long samples);
@@ -49,6 +50,7 @@ namespace gr {
void set_type(noise_type_t type);
void set_amplitude(float ampl);
void generate();
+ const std::vector<@TYPE@>& samples() const;
noise_type_t type() const { return d_type; }
float amplitude() const { return d_ampl; }
diff --git a/gr-analog/python/analog/qa_fastnoise.py b/gr-analog/python/analog/qa_fastnoise.py
index 91e1cb87b7..f712d66ca7 100644
--- a/gr-analog/python/analog/qa_fastnoise.py
+++ b/gr-analog/python/analog/qa_fastnoise.py
@@ -20,32 +20,120 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gr_unittest, analog
+from gnuradio import gr, gr_unittest, analog, blocks
+import numpy
+
class test_fastnoise_source(gr_unittest.TestCase):
def setUp (self):
- self.tb = gr.top_block ()
+
+ self.num = 2**22
+ self.num_items = 10**6
+ self.default_args = {"samples": self.num, "seed": 43, "ampl": 1}
def tearDown (self):
- self.tb = None
+ pass
+
+ def run_test_real(self, form):
+ """ Run test case with float input/output
+ """
+ tb = gr.top_block()
+ src = analog.fastnoise_source_f(type=form, **self.default_args)
+ head = blocks.head(nitems=self.num_items, sizeof_stream_item=gr.sizeof_float)
+ sink = blocks.vector_sink_f()
+ tb.connect(src, head, sink)
+ tb.run()
+ return numpy.array(sink.data())
+
+ def run_test_complex(self, form):
+ """ Run test case with complex input/output
+ """
+ tb = gr.top_block()
+ src = analog.fastnoise_source_c(type=form, **self.default_args)
+ head = blocks.head(nitems=self.num_items, sizeof_stream_item=gr.sizeof_gr_complex)
+ sink = blocks.vector_sink_c()
+ tb.connect(src, head, sink)
+ tb.run()
+ return numpy.array(sink.data())
+
+ def test_001_real_uniform_moments(self):
+
+ data = self.run_test_real(analog.GR_UNIFORM)
+
+ self.assertAlmostEqual(min(data), -1, places=4)
+ self.assertAlmostEqual(max(data), 1, places=4)
+
+ # mean, variance
+ self.assertAlmostEqual(data.mean(), 0, places=2)
+ self.assertAlmostEqual(data.var(), (1-(-1))**2./12, places=3)
+
+ def test_001_real_gaussian_moments(self):
+ data = self.run_test_real(analog.GR_GAUSSIAN)
+
+ # mean, variance
+ self.assertAlmostEqual(data.mean(), 0, places=2)
+ self.assertAlmostEqual(data.var(), 1, places=2)
- def test_001(self):
- # Just confirm that we can instantiate a noise source
- op = analog.fastnoise_source_f(analog.GR_GAUSSIAN, 10, 10)
+ def test_001_real_laplacian_moments(self):
+ data = self.run_test_real(analog.GR_LAPLACIAN)
- def test_002(self):
- # Test get methods
- set_type = analog.GR_GAUSSIAN
- set_ampl = 10
- op = analog.fastnoise_source_f(set_type, set_ampl, 10)
- get_type = op.type()
- get_ampl = op.amplitude()
+ # mean, variance
+ self.assertAlmostEqual(data.mean(), 0, places=2)
+ self.assertAlmostEqual(data.var(), 2, places=2)
- self.assertEqual(get_type, set_type)
- self.assertEqual(get_ampl, set_ampl)
+ def test_001_complex_uniform_moments(self):
+ data = self.run_test_complex(analog.GR_UNIFORM)
+ # mean, variance
+ self.assertAlmostEqual(data.real.mean(), 0, places=2)
+ self.assertAlmostEqual(data.real.var(), 0.5*(1-(-1))**2./12, places=3)
+ self.assertAlmostEqual(data.imag.mean(), 0, places=2)
+ self.assertAlmostEqual(data.imag.var(), 0.5*(1-(-1))**2./12, places=3)
+
+ def test_001_complex_gaussian_moments(self):
+ data = self.run_test_complex(analog.GR_GAUSSIAN)
+
+ # mean, variance
+ self.assertAlmostEqual(data.real.mean(), 0, places=2)
+ self.assertAlmostEqual(data.real.var(), 0.5, places=2)
+
+ self.assertAlmostEqual(data.imag.mean(), 0, places=2)
+ self.assertAlmostEqual(data.imag.var(), 0.5, places=2)
+
+ def test_002_real_uniform_reproducibility(self):
+ data1 = self.run_test_real(analog.GR_UNIFORM)
+ data2 = self.run_test_real(analog.GR_UNIFORM)
+
+ # It's pseudoramdo thus must be equal
+ self.assertTrue(numpy.array_equal(data1, data2))
+
+ def test_002_real_gaussian_reproducibility(self):
+ data1 = self.run_test_real(analog.GR_GAUSSIAN)
+ data2 = self.run_test_real(analog.GR_GAUSSIAN)
+
+ self.assertTrue(numpy.array_equal(data1, data2))
+
+ def test_003_real_uniform_pool(self):
+ src = analog.fastnoise_source_f(type=analog.GR_UNIFORM, **self.default_args)
+ src2 = analog.fastnoise_source_f(type=analog.GR_UNIFORM, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_real_gaussian_pool(self):
+ src = analog.fastnoise_source_f(type=analog.GR_GAUSSIAN, **self.default_args)
+ src2 = analog.fastnoise_source_f(type=analog.GR_GAUSSIAN, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_cmplx_gaussian_pool(self):
+ src = analog.fastnoise_source_c(type=analog.GR_GAUSSIAN, **self.default_args)
+ src2 = analog.fastnoise_source_c(type=analog.GR_GAUSSIAN, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_cmplx_uniform_pool(self):
+ src = analog.fastnoise_source_c(type=analog.GR_UNIFORM, **self.default_args)
+ src2 = analog.fastnoise_source_c(type=analog.GR_UNIFORM, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_real_laplacian_pool(self):
+ src = analog.fastnoise_source_f(type=analog.GR_LAPLACIAN, **self.default_args)
+ src2 = analog.fastnoise_source_f(type=analog.GR_LAPLACIAN, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
if __name__ == '__main__':
gr_unittest.run(test_fastnoise_source, "test_fastnoise_source.xml")
-
diff --git a/gr-blocks/lib/ConfigChecks.cmake b/gr-blocks/lib/ConfigChecks.cmake
index 222a221dc1..1effaa8360 100644
--- a/gr-blocks/lib/ConfigChecks.cmake
+++ b/gr-blocks/lib/ConfigChecks.cmake
@@ -89,10 +89,3 @@ CHECK_CXX_SOURCE_COMPILES("
" HAVE_COSF
)
GR_ADD_COND_DEF(HAVE_COSF)
-
-CHECK_CXX_SOURCE_COMPILES("
- #include <stdlib.h>
- int main(){srand48(0); drand48(); lrand48(); return 0;}
- " HAVE_RAND48
-)
-GR_ADD_COND_DEF(HAVE_RAND48)
diff --git a/gr-blocks/lib/test_tag_variable_rate_ff_impl.cc b/gr-blocks/lib/test_tag_variable_rate_ff_impl.cc
index ec239c9fa7..cca86ad832 100644
--- a/gr-blocks/lib/test_tag_variable_rate_ff_impl.cc
+++ b/gr-blocks/lib/test_tag_variable_rate_ff_impl.cc
@@ -26,10 +26,12 @@
#include "test_tag_variable_rate_ff_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/xoroshiro128p.h>
#include <string.h>
#include <iostream>
#include <iomanip>
#include <stdexcept>
+#include <stdint.h>
using namespace pmt;
@@ -57,11 +59,7 @@ namespace gr {
d_new_in = 0;
d_last_out = 0;
-#ifdef HAVE_RAND48
- srand48(time(NULL));
-#else
- srand(time(NULL));
-#endif
+ xoroshiro128p_seed(d_rng_state, 4 /* chosen by fair dice roll */);
}
test_tag_variable_rate_ff_impl::~test_tag_variable_rate_ff_impl()
@@ -82,11 +80,7 @@ namespace gr {
GR_LOG_DEBUG(d_logger, boost::format("noutput_items: %1%") % noutput_items);
if(d_update_once) {
-#ifdef HAVE_RAND48
- if(drand48() > 0.5) {
-#else
- if (rand() > RAND_MAX / 2) {
-#endif
+ if (xoroshiro128p_next(d_rng_state) > (UINT64_MAX / 2)){
d_rrate += d_update_step;
}
else {
@@ -103,11 +97,7 @@ namespace gr {
while(i < ninput_items[0]) {
if(!d_update_once) {
-#ifdef HAVE_RAND48
- if(drand48() > 0.5) {
-#else
- if (rand() > RAND_MAX / 2) {
-#endif
+ if (xoroshiro128p_next(d_rng_state) > (UINT64_MAX / 2)){
d_rrate += d_update_step;
}
else {
diff --git a/gr-blocks/lib/test_tag_variable_rate_ff_impl.h b/gr-blocks/lib/test_tag_variable_rate_ff_impl.h
index 0335ab6e66..a02bce1ccf 100644
--- a/gr-blocks/lib/test_tag_variable_rate_ff_impl.h
+++ b/gr-blocks/lib/test_tag_variable_rate_ff_impl.h
@@ -36,6 +36,7 @@ namespace gr {
double d_accum;
double d_rrate;
uint64_t d_old_in, d_new_in, d_last_out;
+ uint64_t d_rng_state[2];
public:
test_tag_variable_rate_ff_impl(bool update_once=false,
diff --git a/gr-channels/lib/selective_fading_model_impl.cc b/gr-channels/lib/selective_fading_model_impl.cc
index dfd7b74ca9..3594ec4aa0 100644
--- a/gr-channels/lib/selective_fading_model_impl.cc
+++ b/gr-channels/lib/selective_fading_model_impl.cc
@@ -95,7 +95,7 @@ namespace gr {
gr_complex ff_H(d_faders[j]->next_sample());
for(size_t k=0; k<d_taps.size(); k++){
float dist = k-d_delays[j];
- float interpmag = d_sintable.sinc(2*M_PI*dist);
+ float interpmag = d_sintable.sinc(M_PI*dist);
d_taps[k] += ff_H * interpmag * d_mags[j];
}
}
diff --git a/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t b/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t
index b08bdde08f..5ccc40a3ae 100644
--- a/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t
+++ b/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t
@@ -62,37 +62,29 @@ namespace gr {
void
@IMPL_NAME@::set_vector_from_pmt(std::vector<gr_complex> &symbol_table, pmt::pmt_t &symbol_table_pmt) {
- symbol_table.resize(0);
- for (unsigned int i=0; i<pmt::length(symbol_table_pmt); i++) {
- symbol_table.push_back(pmt::c32vector_ref(symbol_table_pmt, i));
- }
+ size_t length;
+ const gr_complex *elements = pmt::c32vector_elements(symbol_table_pmt, length);
+ symbol_table.assign(elements, elements + length);
}
void
@IMPL_NAME@::set_vector_from_pmt(std::vector<float> &symbol_table, pmt::pmt_t &symbol_table_pmt) {
- symbol_table.resize(0);
- for (unsigned int i=0; i<pmt::length(symbol_table_pmt); i++) {
- float f = pmt::f32vector_ref(symbol_table_pmt, i);
- symbol_table.push_back(f);
- }
+ size_t length;
+ const float *elements = pmt::f32vector_elements(symbol_table_pmt, length);
+ symbol_table.assign(elements, elements + length);
}
-
+
void
@IMPL_NAME@::handle_set_symbol_table(pmt::pmt_t symbol_table_pmt)
{
- std::vector<@O_TYPE@> symbol_table;
- set_vector_from_pmt(symbol_table, symbol_table_pmt);
- set_symbol_table(symbol_table);
+ set_vector_from_pmt(d_symbol_table, symbol_table_pmt);
}
-
void
@IMPL_NAME@::set_symbol_table(const std::vector<@O_TYPE@> &symbol_table)
{
- d_symbol_table.resize(0);
- for (unsigned int i=0; i<symbol_table.size(); i++) {
- d_symbol_table.push_back(symbol_table[i]);
- }
+ gr::thread::scoped_lock lock(d_setlock);
+ d_symbol_table = symbol_table;
}
int
@@ -100,6 +92,7 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
+ gr::thread::scoped_lock lock(d_setlock);
assert(noutput_items % d_D == 0);
assert(input_items.size() == output_items.size());
int nstreams = input_items.size();
@@ -114,7 +107,6 @@ namespace gr {
// per stream processing
for(int i = 0; i < noutput_items / d_D; i++) {
-
std::vector<tag_t> tags_now;
tchecker.get_tags(tags_now, i+nitems_read(m));
for (unsigned int j=0; j<tags_now.size(); j++) {
diff --git a/gr-filter/grc/filter_pfb_channelizer.xml b/gr-filter/grc/filter_pfb_channelizer.xml
index 446acf0591..9b119dcdc1 100644
--- a/gr-filter/grc/filter_pfb_channelizer.xml
+++ b/gr-filter/grc/filter_pfb_channelizer.xml
@@ -33,7 +33,7 @@ self.$(id).declare_sample_delay($samp_delay)
<type>real_vector</type>
</param>
<param>
- <name>Over Sample Ratio</name>
+ <name>Oversampling Ratio</name>
<key>osr</key>
<value>1.0</value>
<type>real</type>
diff --git a/gr-filter/include/gnuradio/filter/pfb_arb_resampler.h b/gr-filter/include/gnuradio/filter/pfb_arb_resampler.h
index 2af56e5f7f..cd4f940df5 100644
--- a/gr-filter/include/gnuradio/filter/pfb_arb_resampler.h
+++ b/gr-filter/include/gnuradio/filter/pfb_arb_resampler.h
@@ -86,7 +86,7 @@ namespace gr {
* attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
*
* The theory behind this block can be found in Chapter 7.5 of
- * the following book.
+ * the following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
@@ -399,7 +399,7 @@ namespace gr {
* attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
*
* The theory behind this block can be found in Chapter 7.5 of
- * the following book.
+ * the following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
diff --git a/gr-filter/include/gnuradio/filter/pfb_arb_resampler_fff.h b/gr-filter/include/gnuradio/filter/pfb_arb_resampler_fff.h
index aadfb778dc..fa2f98cb19 100644
--- a/gr-filter/include/gnuradio/filter/pfb_arb_resampler_fff.h
+++ b/gr-filter/include/gnuradio/filter/pfb_arb_resampler_fff.h
@@ -86,7 +86,7 @@ namespace gr {
* attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
*
* The theory behind this block can be found in Chapter 7.5 of the
- * following book.
+ * following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
diff --git a/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h b/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h
index 91ef57e728..92e0097d16 100644
--- a/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h
@@ -42,8 +42,8 @@ namespace gr {
* <EM>fs</EM> divided by the number of channels, <EM>M</EM>.
*
* The PFB channelizer code takes the taps generated above and builds
- * a set of filters. The set contains <EM>M</EM> number of filters
- * and each filter contains ceil(taps.size()/decim) number of taps.
+ * a set of filters. The set contains <EM>M</EM>filters
+ * and each filter contains ceil(taps.size()/decim) taps.
* Each tap from the filter prototype is sequentially inserted into
* the next filter. When all of the input taps are used, the remaining
* filters in the filterbank are filled out with 0's to make sure each
@@ -77,12 +77,12 @@ namespace gr {
* bandwidth of <EM>TB</EM>. We can also specify the out-of-band
* attenuation to use, <EM>ATT</EM>, and the filter window
* function (a Blackman-harris window in this case). The first input
- * is the gain of the filter, which we specify here as unity.
+ * is the gain of the filter, which we specify here as unity.
*
- * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
- * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
*
- * The filter output can also be overs ampled. The over sampling rate
+ * The filter output can also be oversampled. The oversampling rate
* is the ratio of the the actual output sampling rate to the normal
* output sampling rate. It must be rationally related to the number
* of channels as N/i for i in [1,N], which gives an outputsample rate
@@ -96,7 +96,7 @@ namespace gr {
* so the output rate would be 1200 Hz.
*
* The theory behind this block can be found in Chapter 6 of
- * the following book.
+ * the following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
@@ -121,7 +121,7 @@ namespace gr {
* channels <EM>M</EM>
* \param taps (vector/list of floats) The prototype filter to
* populate the filterbank.
- * \param oversample_rate (float) The over sampling rate is the
+ * \param oversample_rate (float) The oversampling rate is the
* ratio of the the actual output
* sampling rate to the normal
* output sampling rate. It must
@@ -135,7 +135,7 @@ namespace gr {
*
* For example, for 6 channels
* with fs = 6000 Hz, the normal
- * rateis 6000/6 = 1000
+ * rate is 6000/6 = 1000
* Hz. Allowable oversampling
* rates are 6/6, 6/5, 6/4, 6/3,
* 6/2, and 6/1 where the output
diff --git a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
index 5f0f2700b7..e0dd3125cd 100644
--- a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
@@ -73,16 +73,16 @@ namespace gr {
* attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
*
* The PFB decimator code takes the taps generated above and
- * builds a set of filters. The set contains <EM>decim</EM> number
- * of filters and each filter contains ceil(taps.size()/decim)
- * number of taps. Each tap from the filter prototype is
+ * builds a set of filters. The set contains <EM>decim</EM>
+ * filters and each filter contains ceil(taps.size()/decim)
+ * taps. Each tap from the filter prototype is
* sequentially inserted into the next filter. When all of the
* input taps are used, the remaining filters in the filterbank
* are filled out with 0's to make sure each filter has the same
* number of taps.
*
* The theory behind this block can be found in Chapter 6 of
- * the following book.
+ * the following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
diff --git a/gr-filter/include/gnuradio/filter/pfb_interpolator_ccf.h b/gr-filter/include/gnuradio/filter/pfb_interpolator_ccf.h
index 7624f9ef25..ea43d1354d 100644
--- a/gr-filter/include/gnuradio/filter/pfb_interpolator_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_interpolator_ccf.h
@@ -61,15 +61,15 @@ namespace gr {
*
* The PFB interpolator code takes the taps generated above and
* builds a set of filters. The set contains <EM>interp</EM>
- * number of filters and each filter contains
- * ceil(taps.size()/interp) number of taps. Each tap from the
+ * filters and each filter contains
+ * ceil(taps.size()/interp) taps. Each tap from the
* filter prototype is sequentially inserted into the next
* filter. When all of the input taps are used, the remaining
* filters in the filterbank are filled out with 0's to make sure
* each filter has the same number of taps.
*
* The theory behind this block can be found in Chapter 7.1 of the
- * following book.
+ * following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems</EM>," Upper Saddle River, NJ: Prentice Hall,
diff --git a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
index f3bedd811b..715574e0c7 100644
--- a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
+++ b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
@@ -46,9 +46,9 @@ namespace gr {
* <EM>M</EM>.
*
* The PFB channelizer code takes the taps generated above and
- * builds a set of filters. The set contains <EM>M</EM> number
- * of filters and each filter contains ceil(taps.size()/decim)
- * number of taps. Each tap from the filter prototype is
+ * builds a set of filters. The set contains <EM>M</EM>
+ * filters and each filter contains ceil(taps.size()/decim)
+ * taps. Each tap from the filter prototype is
* sequentially inserted into the next filter. When all of the
* input taps are used, the remaining filters in the filterbank
* are filled out with 0's to make sure each filter has the same
@@ -86,11 +86,11 @@ namespace gr {
* input is the gain of the filter, which we specify here as
* unity.
*
- * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
- * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
*
* More on the theory of polyphase filterbanks can be found in
- * the following book.
+ * the following book:
*
* <B><EM>f. harris, "Multirate Signal Processing for
* Communication Systems," Upper Saddle River, NJ:
diff --git a/gr-qtgui/grc/qtgui_ber_sink_b.xml b/gr-qtgui/grc/qtgui_ber_sink_b.xml
index da3fc6ebf8..851502a774 100644
--- a/gr-qtgui/grc/qtgui_ber_sink_b.xml
+++ b/gr-qtgui/grc/qtgui_ber_sink_b.xml
@@ -47,7 +47,7 @@ for i in xrange($num_curves):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
<param>
<name>esno</name>
diff --git a/gr-qtgui/grc/qtgui_check_box.xml b/gr-qtgui/grc/qtgui_check_box.xml
index 67c8848a22..a02c83e3cf 100644
--- a/gr-qtgui/grc/qtgui_check_box.xml
+++ b/gr-qtgui/grc/qtgui_check_box.xml
@@ -20,7 +20,8 @@ self._$(id)_choices_inv = dict((v,k) for k,v in self._$(id)_choices.iteritems())
self._$(id)_callback = lambda i: Qt.QMetaObject.invokeMethod($(win), "setChecked", Qt.Q_ARG("bool", self._$(id)_choices_inv[i]))
self._$(id)_callback(self.$id)
$(win).stateChanged.connect(lambda i: self.set_$(id)(self._$(id)_choices[bool(i)]))
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_callback($id)</callback>
<param>
diff --git a/gr-qtgui/grc/qtgui_chooser.xml b/gr-qtgui/grc/qtgui_chooser.xml
index f018354dd4..b91566ae74 100644
--- a/gr-qtgui/grc/qtgui_chooser.xml
+++ b/gr-qtgui/grc/qtgui_chooser.xml
@@ -86,7 +86,8 @@ self._$(id)_callback(self.$id)
self._$(id)_button_group.buttonClicked[int].connect(
lambda i: self.set_$(id)(self._$(id)_options[i]))
#end if
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_callback($id)</callback>
<param>
diff --git a/gr-qtgui/grc/qtgui_const_sink_x.xml b/gr-qtgui/grc/qtgui_const_sink_x.xml
index 755f12f964..6bf31d5190 100644
--- a/gr-qtgui/grc/qtgui_const_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_const_sink_x.xml
@@ -51,7 +51,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_resize($width, $height)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/gr-qtgui/grc/qtgui_edit_box_msg.xml b/gr-qtgui/grc/qtgui_edit_box_msg.xml
index c7c758a612..276cfe9801 100644
--- a/gr-qtgui/grc/qtgui_edit_box_msg.xml
+++ b/gr-qtgui/grc/qtgui_edit_box_msg.xml
@@ -13,7 +13,7 @@
<make>#set $win = 'self._%s_win'%$id
qtgui.edit_box_msg($(type.t), $value, $label, $is_pair, $is_static, $key)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
<param>
<name>Type</name>
diff --git a/gr-qtgui/grc/qtgui_entry.xml b/gr-qtgui/grc/qtgui_entry.xml
index cce2edb4b2..ab35aec858 100644
--- a/gr-qtgui/grc/qtgui_entry.xml
+++ b/gr-qtgui/grc/qtgui_entry.xml
@@ -21,9 +21,12 @@ self._$(id)_line_edit = Qt.QLineEdit(str(self.$id))
self._$(id)_tool_bar.addWidget(self._$(id)_line_edit)
self._$(id)_line_edit.returnPressed.connect(
lambda: self.set_$(id)($(type.conv)(str(self._$(id)_line_edit.text().toAscii()))))
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
+
<callback>Qt.QMetaObject.invokeMethod(self._$(id)_line_edit, "setText", Qt.Q_ARG("QString", $(type.str)($id)))</callback>
+
<param>
<name>Label</name>
<key>label</key>
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml
index 009a184327..5c6595cb33 100644
--- a/gr-qtgui/grc/qtgui_freq_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -54,7 +54,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_frequency_range($fc, $bw)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/gr-qtgui/grc/qtgui_histogram_sink_x.xml b/gr-qtgui/grc/qtgui_histogram_sink_x.xml
index a789d2e4fa..8bf9662b74 100644
--- a/gr-qtgui/grc/qtgui_histogram_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_histogram_sink_x.xml
@@ -53,8 +53,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))
- </make>
+$(gui_hint() % $win)</make>
+
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
<callback>set_color($which, $color)</callback>
diff --git a/gr-qtgui/grc/qtgui_label.xml b/gr-qtgui/grc/qtgui_label.xml
index d67f3d7500..90b77fa968 100644
--- a/gr-qtgui/grc/qtgui_label.xml
+++ b/gr-qtgui/grc/qtgui_label.xml
@@ -26,8 +26,7 @@ else:
$(win).addWidget(Qt.QLabel($label+": "))
self._$(id)_label = Qt.QLabel(str(self._$(id)_formatter(self.$id)))
self._$(id)_tool_bar.addWidget(self._$(id)_label)
-$(gui_hint()($win))
- </make>
+$(gui_hint() % $win)</make>
<callback>self.set_$(id)(self._$(id)_formatter($value))</callback>
<callback>Qt.QMetaObject.invokeMethod(self._$(id)_label, "setText", Qt.Q_ARG("QString", $id))</callback>
diff --git a/gr-qtgui/grc/qtgui_number_sink.xml b/gr-qtgui/grc/qtgui_number_sink.xml
index d10b7325c0..264baae667 100644
--- a/gr-qtgui/grc/qtgui_number_sink.xml
+++ b/gr-qtgui/grc/qtgui_number_sink.xml
@@ -41,7 +41,8 @@ for i in xrange($nconnections):
self.$(id).enable_autoscale($autoscale)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_update_time($update_time)</callback>
<param_tab_order>
diff --git a/gr-qtgui/grc/qtgui_push_button.xml b/gr-qtgui/grc/qtgui_push_button.xml
index a535bb6473..e4f598e725 100644
--- a/gr-qtgui/grc/qtgui_push_button.xml
+++ b/gr-qtgui/grc/qtgui_push_button.xml
@@ -18,8 +18,10 @@ $win = Qt.QPushButton($label)
self._$(id)_choices = {'Pressed': $pressed, 'Released': $released}
$(win).pressed.connect(lambda: self.set_$(id)(self._$(id)_choices['Pressed']))
$(win).released.connect(lambda: self.set_$(id)(self._$(id)_choices['Released']))
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
+
<param>
<name>Label</name>
<key>label</key>
diff --git a/gr-qtgui/grc/qtgui_range.xml b/gr-qtgui/grc/qtgui_range.xml
index 71b614cc5e..0999311a0b 100644
--- a/gr-qtgui/grc/qtgui_range.xml
+++ b/gr-qtgui/grc/qtgui_range.xml
@@ -17,7 +17,8 @@
#end if
$(range) = Range($start, $stop, $step, $value, $min_len)
$(win) = RangeWidget($range, self.set_$(id), $label, "$widget", $rangeType)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
<param>
diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml
index 7488ea59d8..4dbf0e6375 100644
--- a/gr-qtgui/grc/qtgui_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_sink_x.xml
@@ -25,7 +25,7 @@ qtgui.$(type.fcn)(
)
self.$(id).set_update_time(1.0/$rate)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))
+$(gui_hint() % $win)
self.$(id).enable_rf_freq($showrf)
diff --git a/gr-qtgui/grc/qtgui_tab_widget.xml b/gr-qtgui/grc/qtgui_tab_widget.xml
index 1bbadc8e51..fc8ad0553a 100644
--- a/gr-qtgui/grc/qtgui_tab_widget.xml
+++ b/gr-qtgui/grc/qtgui_tab_widget.xml
@@ -21,7 +21,8 @@ self.$(id)_grid_layout_$(i) = Qt.QGridLayout()
self.$(id)_layout_$(i).addLayout(self.$(id)_grid_layout_$(i))
$(win).addTab(self.$(id)_widget_$(i), $label)
#end for
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<param>
<name>Num Tabs</name>
<key>num_tabs</key>
diff --git a/gr-qtgui/grc/qtgui_time_raster_x.xml b/gr-qtgui/grc/qtgui_time_raster_x.xml
index 0359dc3b71..2d2f3cbff4 100644
--- a/gr-qtgui/grc/qtgui_time_raster_x.xml
+++ b/gr-qtgui/grc/qtgui_time_raster_x.xml
@@ -41,7 +41,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_num_rows($nrows)</callback>
<callback>set_num_cols($ncols)</callback>
<callback>set_multiplier($mult)</callback>
diff --git a/gr-qtgui/grc/qtgui_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml
index b44a8fe52d..a263e6ef98 100644
--- a/gr-qtgui/grc/qtgui_time_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_time_sink_x.xml
@@ -75,7 +75,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
#end if
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_time_domain_axis($min, $max)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/gr-qtgui/grc/qtgui_vector_sink_f.xml b/gr-qtgui/grc/qtgui_vector_sink_f.xml
index 9f40d57729..1c17b8256a 100644
--- a/gr-qtgui/grc/qtgui_vector_sink_f.xml
+++ b/gr-qtgui/grc/qtgui_vector_sink_f.xml
@@ -46,7 +46,8 @@ for i in xrange($nconnections):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_update_time($update_time)</callback>
<callback>set_title($title)</callback>
<callback>set_color($which, $color)</callback>
diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
index cdecd5cce1..206318e30d 100644
--- a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
@@ -47,7 +47,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_intensity_range($int_min, $int_max)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_frequency_range($fc, $bw)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/grc/core/Param.py b/grc/core/Param.py
index 00c9e7d827..01697919d0 100644
--- a/grc/core/Param.py
+++ b/grc/core/Param.py
@@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import ast
import weakref
import re
+import textwrap
from . import Constants
from .Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES
@@ -212,7 +213,7 @@ class Param(Element):
self._value = value or ''
self._default = value
self._init = False
- self._hostage_cells = list()
+ self.hostage_cells = set()
self.template_arg = TemplateArg(self)
def get_types(self):
@@ -395,7 +396,6 @@ class Param(Element):
self._init = True
self._lisitify_flag = False
self._stringify_flag = False
- self._hostage_cells = list()
t = self.get_type()
v = self.get_value()
@@ -533,38 +533,10 @@ class Param(Element):
# GUI Position/Hint
#########################
elif t == 'gui_hint':
- if ':' in v:
- tab, pos = v.split(':')
- elif '@' in v:
- tab, pos = v, ''
- else:
- tab, pos = '', v
-
- if '@' in tab:
- tab, index = tab.split('@')
+ if (self.get_parent().get_state() == Constants.BLOCK_DISABLED):
+ return ''
else:
- index = '?'
-
- # TODO: Problem with this code. Produces bad tabs
- widget_str = ({
- (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)',
- (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)',
- (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)',
- (False, False): 'self.top_layout.addWidget(%(widget)s)',
- }[bool(tab), bool(pos)]) % {'tab': tab, 'index': index, 'widget': '%s', 'pos': pos}
-
- # FIXME: Move replace(...) into the make template of the qtgui blocks
- # Return a string here
- class GuiHint(object):
- def __init__(self, ws):
- self._ws = ws
-
- def __call__(self, w):
- return (self._ws.replace('addWidget', 'addLayout') if 'layout' in w else self._ws) % w
-
- def __str__(self):
- return self._ws
- return GuiHint(widget_str)
+ return self.parse_gui_hint(v)
#########################
# Grid Position Type
#########################
@@ -590,12 +562,12 @@ class Param(Element):
# Calculate hostage cells
for r in range(row_span):
for c in range(col_span):
- self._hostage_cells.append((my_parent, (row+r, col+c)))
+ self.hostage_cells.append((my_parent, (row + r, col + c)))
# Avoid collisions
params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
for param in params:
for parent, cell in param._hostage_cells:
- if (parent, cell) in self._hostage_cells:
+ if (parent, cell) in self.hostage_cells:
raise Exception('Another graphical element is using parent "{0}", cell "{1}".'.format(str(parent), str(cell)))
return e
#########################
@@ -753,3 +725,113 @@ class Param(Element):
n['key'] = self.get_key()
n['value'] = self.get_value()
return n
+
+ ##############################################
+ # GUI Hint
+ ##############################################
+ def parse_gui_hint(self, v):
+ """
+ Parse/validate gui hint value.
+
+ Args:
+ v: gui_hint string from a block's 'gui_hint' param
+
+ Returns:
+ string of python code for positioning GUI elements in pyQT
+ """
+ self.hostage_cells.clear()
+
+ # Parsing
+ if ':' in v:
+ tab, pos = v.split(':')
+ elif ',' in v:
+ tab, pos = '', v
+ else:
+ tab, pos = v, ''
+
+ if '@' in tab:
+ tab, index = tab.split('@')
+ else:
+ index = '0'
+ index = int(index)
+
+ # Validation
+ def parse_pos():
+ e = self.get_parent().get_parent().evaluate(pos)
+
+ if not isinstance(e, (list, tuple)) or len(e) not in (2, 4) or not all(isinstance(ei, int) for ei in e):
+ raise Exception('Invalid GUI Hint entered: {e!r} (Must be a list of {{2,4}} non-negative integers).'.format(e=e))
+
+ if len(e) == 2:
+ row, col = e
+ row_span = col_span = 1
+ else:
+ row, col, row_span, col_span = e
+
+ if (row < 0) or (col < 0):
+ raise Exception('Invalid GUI Hint entered: {e!r} (non-negative integers only).'.format(e=e))
+
+ if (row_span < 1) or (col_span < 1):
+ raise Exception('Invalid GUI Hint entered: {e!r} (positive row/column span required).'.format(e=e))
+
+ return row, col, row_span, col_span
+
+ def validate_tab():
+ enabled_blocks = self.get_parent().get_parent().iter_enabled_blocks()
+ tabs = (block for block in enabled_blocks
+ if block.get_key() == 'qtgui_tab_widget' and block.get_id() == tab)
+ tab_block = next(iter(tabs), None)
+ if not tab_block:
+ raise Exception('Invalid tab name entered: {tab} (Tab name not found).'.format(tab=tab))
+
+ tab_index_size = int(tab_block.get_param('num_tabs').get_value())
+ if index >= tab_index_size:
+ raise Exception('Invalid tab index entered: {tab}@{index} (Index out of range).'.format(
+ tab=tab, index=index))
+
+ # Collision Detection
+ def collision_detection(row, col, row_span, col_span):
+ my_parent = '{tab}@{index}'.format(tab=tab, index=index) if tab else 'main'
+ # Calculate hostage cells
+ for r in range(row, row + row_span):
+ for c in range(col, col + col_span):
+ self.hostage_cells.add((my_parent, (r, c)))
+
+ for other in self.get_all_params('gui_hint'):
+ if other is self:
+ continue
+ collision = next(iter(self.hostage_cells & other.hostage_cells), None)
+ if collision:
+ raise Exception('Block {block!r} is also using parent {parent!r}, cell {cell!r}.'.format(
+ block=other.get_parent().get_id(), parent=collision[0], cell=collision[1]
+ ))
+
+ # Code Generation
+ if tab:
+ validate_tab()
+ layout = '{tab}_grid_layout_{index}'.format(tab=tab, index=index)
+ else:
+ layout = 'top_grid_layout'
+
+ widget = '%s' # to be fill-out in the mail template
+
+ if pos:
+ row, col, row_span, col_span = parse_pos()
+ collision_detection(row, col, row_span, col_span)
+
+ widget_str = textwrap.dedent("""
+ self.{layout}.addWidget({widget}, {row}, {col}, {row_span}, {col_span})
+ for r in range({row}, {row_end}):
+ self.{layout}.setRowStretch(r, 1)
+ for c in range({col}, {col_end}):
+ self.{layout}.setColumnStretch(c, 1)
+ """.strip('\n')).format(
+ layout=layout, widget=widget,
+ row=row, row_span=row_span, row_end=row+row_span,
+ col=col, col_span=col_span, col_end=col+col_span,
+ )
+
+ else:
+ widget_str = 'self.{layout}.addWidget({widget})'.format(layout=layout, widget=widget)
+
+ return widget_str
diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py
index 3b82be9084..f42392e485 100644
--- a/grc/core/generator/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -399,6 +399,6 @@ class QtHierBlockGenerator(HierBlockGenerator):
block_n['make'] += (
"\n#set $win = 'self.%s' % $id"
- "\n${gui_hint()($win)}"
+ "\n${gui_hint() % $win}"
)
return n
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
index 900cbd3151..258b8b787f 100644
--- a/grc/gui/BlockTreeWindow.py
+++ b/grc/gui/BlockTreeWindow.py
@@ -58,7 +58,8 @@ undocumented#slurp
CAT_MARKUP_TMPL = """
#set $name = $cat[-1]
#if len($cat) > 1
-Category: $cat[-1]
+#silent from xml.sax.saxutils import escape
+Category: #echo escape($cat[-1])
##
#elif $name == 'Core'
Module: Core