summaryrefslogtreecommitdiff
path: root/gnuradio-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src')
-rw-r--r--gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S2
-rw-r--r--gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S2
-rw-r--r--gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S2
-rw-r--r--gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S2
-rw-r--r--gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S2
-rw-r--r--gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S2
-rw-r--r--gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S2
-rw-r--r--gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S2
-rw-r--r--gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S2
-rw-r--r--gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S2
-rw-r--r--gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S2
-rw-r--r--gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S2
-rw-r--r--gnuradio-core/src/lib/filter/complex_dotprod_sse.S2
-rw-r--r--gnuradio-core/src/lib/filter/complex_dotprod_sse64.S2
-rw-r--r--gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S2
-rw-r--r--gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S2
-rw-r--r--gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S2
-rw-r--r--gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S2
-rw-r--r--gnuradio-core/src/lib/filter/float_dotprod_3dnow.S2
-rw-r--r--gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S2
-rw-r--r--gnuradio-core/src/lib/filter/float_dotprod_sse.S2
-rw-r--r--gnuradio-core/src/lib/filter/float_dotprod_sse64.S2
-rw-r--r--gnuradio-core/src/lib/filter/short_dotprod_mmx.S2
-rw-r--r--gnuradio-core/src/lib/filter/short_dotprod_mmx64.S2
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/general/general.i5
-rw-r--r--gnuradio-core/src/lib/general/gr_block_gateway.cc184
-rw-r--r--gnuradio-core/src/lib/general/gr_block_gateway.h212
-rw-r--r--gnuradio-core/src/lib/general/gr_block_gateway.i46
-rw-r--r--gnuradio-core/src/lib/general/gr_message_strobe.cc75
-rw-r--r--gnuradio-core/src/lib/general/gr_message_strobe.h62
-rw-r--r--gnuradio-core/src/lib/general/gr_message_strobe.i30
-rw-r--r--gnuradio-core/src/lib/general/gr_nop.cc3
-rw-r--r--gnuradio-core/src/lib/general/gr_skiphead.cc4
-rw-r--r--gnuradio-core/src/lib/general/gri_control_loop.cc23
-rw-r--r--gnuradio-core/src/lib/general/gri_control_loop.h39
-rw-r--r--gnuradio-core/src/lib/io/CMakeLists.txt5
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.cc64
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.h55
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.i30
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu.cc69
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu.h38
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu.i30
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc132
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h63
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i31
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc137
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h76
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i31
-rw-r--r--gnuradio-core/src/lib/io/gr_udp_source.cc10
-rw-r--r--gnuradio-core/src/lib/io/io.i8
-rw-r--r--gnuradio-core/src/lib/runtime/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.cc126
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.h92
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.i6
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc47
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h115
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.i14
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.cc6
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.h5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc6
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_registry.cc76
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_registry.h42
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc25
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flowgraph.cc9
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flowgraph.h3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.cc30
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.h15
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.i15
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc31
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_msg_accepter.cc4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_msg_accepter.h2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_detail.cc40
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_detail.h26
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc50
-rw-r--r--gnuradio-core/src/lib/runtime/qa_gr_top_block.cc143
-rw-r--r--gnuradio-core/src/lib/runtime/qa_gr_top_block.h8
-rw-r--r--gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc8
-rw-r--r--gnuradio-core/src/python/build_utils.py8
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt8
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/__init__.py22
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/gateway.py215
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py235
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pdu.py70
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/top_block.py6
87 files changed, 2862 insertions, 169 deletions
diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S
index 0cd686736..546a4a6f3 100644
--- a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S
+++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S
@@ -52,7 +52,7 @@
.file "3dnow_float_dotprod_really_simple.s"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl sse_float_dotprod
diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S
index 5af3fc5c9..c721c3601 100644
--- a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S
+++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S
@@ -52,7 +52,7 @@
.file "3dnow_float_dotprod_simple.s"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl sse_float_dotprod
diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S
index 8844e5108..f66356337 100644
--- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S
+++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S
@@ -55,7 +55,7 @@
#include "assembly.h"
.file "ccomplex_dotprod_3dnow.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(ccomplex_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S
index d92fe17a3..e81d21993 100644
--- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S
+++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S
@@ -56,7 +56,7 @@
.file "ccomplex_dotprod_3dnow64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(ccomplex_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S
index c4a02d7fb..22c390bdd 100644
--- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S
+++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S
@@ -55,7 +55,7 @@
#include "assembly.h"
.file "ccomplex_dotprod_3dnowext.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(ccomplex_dotprod_3dnowext)
diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S
index c4f9e1970..75608914b 100644
--- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S
+++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S
@@ -55,7 +55,7 @@
#include "assembly.h"
.file "ccomplex_dotprod_3dnowext64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(ccomplex_dotprod_3dnowext)
diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S
index b50a3690d..3d16c352e 100644
--- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S
+++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S
@@ -55,7 +55,7 @@
#include "assembly.h"
.file "ccomplex_dotprod_sse.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(ccomplex_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S
index ef89ae638..95ac3dac3 100644
--- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S
+++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S
@@ -56,7 +56,7 @@
.file "ccomplex_dotprod_sse64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(ccomplex_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S
index df7761c40..be49bb863 100644
--- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S
+++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S
@@ -53,7 +53,7 @@
#include "assembly.h"
.file "complex_dotprod_3dnow.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(complex_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S
index ac5a7d1be..f1c813078 100644
--- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S
+++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S
@@ -54,7 +54,7 @@
.file "complex_dotprod_3dnow64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(complex_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S
index 1d4be32c3..52f04f10c 100644
--- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S
+++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S
@@ -53,7 +53,7 @@
#include "assembly.h"
.file "complex_dotprod_3dnowext.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(complex_dotprod_3dnowext)
diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S
index 018fefe28..6d7ad5ad4 100644
--- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S
+++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S
@@ -54,7 +54,7 @@
.file "complex_dotprod_3dnowext64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(complex_dotprod_3dnowext)
diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S
index fff1057dd..fb998cc45 100644
--- a/gnuradio-core/src/lib/filter/complex_dotprod_sse.S
+++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S
@@ -56,7 +56,7 @@
.file "complex_dotprod_sse.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(complex_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S
index 77f0c3178..67d3519e4 100644
--- a/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S
+++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S
@@ -56,7 +56,7 @@
.file "complex_dotprod_sse64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(complex_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S
index a4e69461e..536e46dc1 100644
--- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S
+++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S
@@ -53,7 +53,7 @@
.file "fcomplex_dotprod_3dnow.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(fcomplex_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S
index 9bbf56301..d9a695949 100644
--- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S
+++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S
@@ -53,7 +53,7 @@
.file "fcomplex_dotprod_3dnow64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(fcomplex_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S
index e516f0a61..4c5e956f2 100644
--- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S
+++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S
@@ -56,7 +56,7 @@
.file "fcomplex_dotprod_sse.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(fcomplex_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S
index 605d87130..53a4f25e0 100644
--- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S
+++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S
@@ -56,7 +56,7 @@
.file "fcomplex_dotprod_sse64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(fcomplex_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S
index 914b652af..cdebe9bc3 100644
--- a/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S
+++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S
@@ -54,7 +54,7 @@
.file "float_dotprod_3dnow.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(float_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S
index 6670553a3..1e859d75a 100644
--- a/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S
+++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S
@@ -54,7 +54,7 @@
.file "float_dotprod_3dnow64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(float_dotprod_3dnow)
diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse.S b/gnuradio-core/src/lib/filter/float_dotprod_sse.S
index beddc75b0..66604526d 100644
--- a/gnuradio-core/src/lib/filter/float_dotprod_sse.S
+++ b/gnuradio-core/src/lib/filter/float_dotprod_sse.S
@@ -54,7 +54,7 @@
.file "float_dotprod_sse.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(float_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse64.S b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S
index 3d425b26b..0dd0764c5 100644
--- a/gnuradio-core/src/lib/filter/float_dotprod_sse64.S
+++ b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S
@@ -54,7 +54,7 @@
.file "float_dotprod_sse64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 4
.globl GLOB_SYMB(float_dotprod_sse)
diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S
index 48f634a18..0f6801e4b 100644
--- a/gnuradio-core/src/lib/filter/short_dotprod_mmx.S
+++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S
@@ -37,7 +37,7 @@
.file "short_dotprod_mmx.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 3
.globl GLOB_SYMB(short_dotprod_mmx)
diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S
index c8c9da30a..bafd0e04e 100644
--- a/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S
+++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S
@@ -37,7 +37,7 @@
.file "short_dotprod_mmx64.S"
- .version "01.01"
+// .version "01.01"
.text
.p2align 3
.globl GLOB_SYMB(short_dotprod_mmx)
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index 3cf7f74e4..4c99acfc3 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -187,6 +187,7 @@ set(gr_core_general_triple_threats
gr_agc2_ff
gr_align_on_samplenumbers_ss
gr_bin_statistics_f
+ gr_block_gateway
gr_bytes_to_syms
gr_char_to_float
gr_char_to_short
@@ -298,6 +299,7 @@ set(gr_core_general_triple_threats
gr_burst_tagger
gr_correlate_access_code_tag_bb
gr_tag_debug
+ gr_message_strobe
)
foreach(file_tt ${gr_core_general_triple_threats})
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index 790549c4d..1446088a2 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+ * Copyright 2004-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -143,6 +143,7 @@
#include <gr_add_ff.h>
#include <gr_vector_map.h>
#include <gr_tag_debug.h>
+#include <gr_message_strobe.h>
%}
%include "gri_control_loop.i"
@@ -266,3 +267,5 @@
%include "gr_add_ff.i"
%include "gr_vector_map.i"
%include "gr_tag_debug.i"
+%include "gr_block_gateway.i"
+%include "gr_message_strobe.i"
diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.cc b/gnuradio-core/src/lib/general/gr_block_gateway.cc
new file mode 100644
index 000000000..79b42803a
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_block_gateway.cc
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+#include <gr_block_gateway.h>
+#include <gr_io_signature.h>
+#include <iostream>
+#include <boost/bind.hpp>
+
+/***********************************************************************
+ * Helper routines
+ **********************************************************************/
+template <typename OutType, typename InType>
+void copy_pointers(OutType &out, const InType &in){
+ out.resize(in.size());
+ for (size_t i = 0; i < in.size(); i++){
+ out[i] = (void *)(in[i]);
+ }
+}
+
+/***********************************************************************
+ * The gr_block gateway implementation class
+ **********************************************************************/
+class gr_block_gateway_impl : public gr_block_gateway{
+public:
+ gr_block_gateway_impl(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+ ):
+ gr_block(name, in_sig, out_sig),
+ _handler(handler),
+ _work_type(work_type)
+ {
+ switch(_work_type){
+ case GR_BLOCK_GW_WORK_GENERAL:
+ _decim = 1; //not relevant, but set anyway
+ _interp = 1; //not relevant, but set anyway
+ break;
+
+ case GR_BLOCK_GW_WORK_SYNC:
+ _decim = 1;
+ _interp = 1;
+ this->set_fixed_rate(true);
+ break;
+
+ case GR_BLOCK_GW_WORK_DECIM:
+ _decim = factor;
+ _interp = 1;
+ break;
+
+ case GR_BLOCK_GW_WORK_INTERP:
+ _decim = 1;
+ _interp = factor;
+ this->set_output_multiple(_interp);
+ break;
+ }
+ }
+
+ /*******************************************************************
+ * Overloads for various scheduler-called functions
+ ******************************************************************/
+ void forecast(
+ int noutput_items,
+ gr_vector_int &ninput_items_required
+ ){
+ switch(_work_type){
+ case GR_BLOCK_GW_WORK_GENERAL:
+ _message.action = gr_block_gw_message_type::ACTION_FORECAST;
+ _message.forecast_args_noutput_items = noutput_items;
+ _message.forecast_args_ninput_items_required = ninput_items_required;
+ _handler->calleval(0);
+ ninput_items_required = _message.forecast_args_ninput_items_required;
+ return;
+
+ default:
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items);
+ return;
+ }
+ }
+
+ int general_work(
+ int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items
+ ){
+ switch(_work_type){
+ case GR_BLOCK_GW_WORK_GENERAL:
+ _message.action = gr_block_gw_message_type::ACTION_GENERAL_WORK;
+ _message.general_work_args_noutput_items = noutput_items;
+ _message.general_work_args_ninput_items = ninput_items;
+ copy_pointers(_message.general_work_args_input_items, input_items);
+ _message.general_work_args_output_items = output_items;
+ _handler->calleval(0);
+ return _message.general_work_args_return_value;
+
+ default:
+ int r = work (noutput_items, input_items, output_items);
+ if (r > 0) consume_each(r*_decim/_interp);
+ return r;
+ }
+ }
+
+ int work(
+ int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items
+ ){
+ _message.action = gr_block_gw_message_type::ACTION_WORK;
+ _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items);
+ if (_message.work_args_ninput_items == 0) return -1;
+ _message.work_args_noutput_items = noutput_items;
+ copy_pointers(_message.work_args_input_items, input_items);
+ _message.work_args_output_items = output_items;
+ _handler->calleval(0);
+ return _message.work_args_return_value;
+ }
+
+ int fixed_rate_noutput_to_ninput(int noutput_items){
+ return (noutput_items*_decim/_interp) + history() - 1;
+ }
+
+ int fixed_rate_ninput_to_noutput(int ninput_items){
+ return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim;
+ }
+
+ bool start(void){
+ _message.action = gr_block_gw_message_type::ACTION_START;
+ _handler->calleval(0);
+ return _message.start_args_return_value;
+ }
+
+ bool stop(void){
+ _message.action = gr_block_gw_message_type::ACTION_STOP;
+ _handler->calleval(0);
+ return _message.stop_args_return_value;
+ }
+
+ gr_block_gw_message_type &gr_block_message(void){
+ return _message;
+ }
+
+private:
+ gr_feval_ll *_handler;
+ gr_block_gw_message_type _message;
+ const gr_block_gw_work_type _work_type;
+ unsigned _decim, _interp;
+};
+
+boost::shared_ptr<gr_block_gateway> gr_make_block_gateway(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+){
+ return boost::shared_ptr<gr_block_gateway>(
+ new gr_block_gateway_impl(handler, name, in_sig, out_sig, work_type, factor)
+ );
+}
diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.h b/gnuradio-core/src/lib/general/gr_block_gateway.h
new file mode 100644
index 000000000..ae91d41b5
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_block_gateway.h
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_GRBLOCK_GATEWAY_H
+#define INCLUDED_GRBLOCK_GATEWAY_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+#include <gr_feval.h>
+
+/*!
+ * The work type enum tells the gateway what kind of block to implement.
+ * The choices are familiar gnuradio block overloads (sync, decim, interp).
+ */
+enum gr_block_gw_work_type{
+ GR_BLOCK_GW_WORK_GENERAL,
+ GR_BLOCK_GW_WORK_SYNC,
+ GR_BLOCK_GW_WORK_DECIM,
+ GR_BLOCK_GW_WORK_INTERP,
+};
+
+/*!
+ * Shared message structure between python and gateway.
+ * Each action type represents a scheduler-called function.
+ */
+struct gr_block_gw_message_type{
+ enum action_type{
+ ACTION_GENERAL_WORK, //dispatch work
+ ACTION_WORK, //dispatch work
+ ACTION_FORECAST, //dispatch forecast
+ ACTION_START, //dispatch start
+ ACTION_STOP, //dispatch stop
+ };
+
+ action_type action;
+
+ int general_work_args_noutput_items;
+ std::vector<int> general_work_args_ninput_items;
+ std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
+ std::vector<void *> general_work_args_output_items;
+ int general_work_args_return_value;
+
+ int work_args_ninput_items;
+ int work_args_noutput_items;
+ std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
+ std::vector<void *> work_args_output_items;
+ int work_args_return_value;
+
+ int forecast_args_noutput_items;
+ std::vector<int> forecast_args_ninput_items_required;
+
+ bool start_args_return_value;
+
+ bool stop_args_return_value;
+};
+
+/*!
+ * The gateway block which performs all the magic.
+ *
+ * The gateway provides access to all the gr_block routines.
+ * The methods prefixed with gr_block__ are renamed
+ * to class methods without the prefix in python.
+ */
+class GR_CORE_API gr_block_gateway : virtual public gr_block{
+public:
+ //! Provide access to the shared message object
+ virtual gr_block_gw_message_type &gr_block_message(void) = 0;
+
+ long gr_block__unique_id(void) const{
+ return gr_block::unique_id();
+ }
+
+ std::string gr_block__name(void) const{
+ return gr_block::name();
+ }
+
+ unsigned gr_block__history(void) const{
+ return gr_block::history();
+ }
+
+ void gr_block__set_history(unsigned history){
+ return gr_block::set_history(history);
+ }
+
+ void gr_block__set_fixed_rate(bool fixed_rate){
+ return gr_block::set_fixed_rate(fixed_rate);
+ }
+
+ bool gr_block__fixed_rate(void) const{
+ return gr_block::fixed_rate();
+ }
+
+ void gr_block__set_output_multiple(int multiple){
+ return gr_block::set_output_multiple(multiple);
+ }
+
+ int gr_block__output_multiple(void) const{
+ return gr_block::output_multiple();
+ }
+
+ void gr_block__consume(int which_input, int how_many_items){
+ return gr_block::consume(which_input, how_many_items);
+ }
+
+ void gr_block__consume_each(int how_many_items){
+ return gr_block::consume_each(how_many_items);
+ }
+
+ void gr_block__produce(int which_output, int how_many_items){
+ return gr_block::produce(which_output, how_many_items);
+ }
+
+ void gr_block__set_relative_rate(double relative_rate){
+ return gr_block::set_relative_rate(relative_rate);
+ }
+
+ double gr_block__relative_rate(void) const{
+ return gr_block::relative_rate();
+ }
+
+ uint64_t gr_block__nitems_read(unsigned int which_input){
+ return gr_block::nitems_read(which_input);
+ }
+
+ uint64_t gr_block__nitems_written(unsigned int which_output){
+ return gr_block::nitems_written(which_output);
+ }
+
+ gr_block::tag_propagation_policy_t gr_block__tag_propagation_policy(void){
+ return gr_block::tag_propagation_policy();
+ }
+
+ void gr_block__set_tag_propagation_policy(gr_block::tag_propagation_policy_t p){
+ return gr_block::set_tag_propagation_policy(p);
+ }
+
+ void gr_block__add_item_tag(
+ unsigned int which_output, const gr_tag_t &tag
+ ){
+ return gr_block::add_item_tag(which_output, tag);
+ }
+
+ void gr_block__add_item_tag(
+ unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F
+ ){
+ return gr_block::add_item_tag(which_output, abs_offset, key, value, srcid);
+ }
+
+ std::vector<gr_tag_t> gr_block__get_tags_in_range(
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end
+ ){
+ std::vector<gr_tag_t> tags;
+ gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end);
+ return tags;
+ }
+
+ std::vector<gr_tag_t> gr_block__get_tags_in_range(
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key
+ ){
+ std::vector<gr_tag_t> tags;
+ gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end, key);
+ return tags;
+ }
+};
+
+/*!
+ * Make a new gateway block.
+ * \param handler the swig director object with callback
+ * \param name the name of the block (Ex: "Shirley")
+ * \param in_sig the input signature for this block
+ * \param out_sig the output signature for this block
+ * \param work_type the type of block overload to implement
+ * \param factor the decimation or interpolation factor
+ * \return a new gateway block
+ */
+GR_CORE_API boost::shared_ptr<gr_block_gateway> gr_make_block_gateway(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+);
+
+#endif /* INCLUDED_GRBLOCK_GATEWAY_H */
diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.i b/gnuradio-core/src/lib/general/gr_block_gateway.i
new file mode 100644
index 000000000..8adafdfea
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_block_gateway.i
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+////////////////////////////////////////////////////////////////////////
+// standard includes
+////////////////////////////////////////////////////////////////////////
+%include <gnuradio.i>
+%include <gr_tags.i>
+%include <gr_feval.i>
+
+////////////////////////////////////////////////////////////////////////
+// block headers
+////////////////////////////////////////////////////////////////////////
+%{
+#include <gr_block_gateway.h>
+%}
+
+////////////////////////////////////////////////////////////////////////
+// data type support
+////////////////////////////////////////////////////////////////////////
+%template(int_vector_t) std::vector<int>;
+%template(void_star_vector_t) std::vector<void *>;
+
+////////////////////////////////////////////////////////////////////////
+// block magic
+////////////////////////////////////////////////////////////////////////
+GR_SWIG_BLOCK_MAGIC(gr,block_gateway);
+%include <gr_block_gateway.h>
diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.cc b/gnuradio-core/src/lib/general/gr_message_strobe.cc
new file mode 100644
index 000000000..6a9f807d1
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_message_strobe.cc
@@ -0,0 +1,75 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_message_strobe.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+
+// public constructor that returns a shared_ptr
+
+gr_message_strobe_sptr
+gr_make_message_strobe (pmt::pmt_t msg, float period_ms)
+{
+ return gnuradio::get_initial_sptr(new gr_message_strobe(msg, period_ms));
+}
+
+gr_message_strobe::gr_message_strobe (pmt::pmt_t msg, float period_ms)
+ : gr_block("message_strobe",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(0, 0, 0)),
+ d_finished(false),
+ d_period_ms(period_ms),
+ d_msg(msg)
+{
+ message_port_register_out(pmt::mp("strobe"));
+ d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_message_strobe::run, this)));
+
+ message_port_register_in(pmt::mp("set_msg"));
+ set_msg_handler(pmt::mp("set_msg"), boost::bind(&gr_message_strobe::set_msg, this, _1));
+}
+
+gr_message_strobe::~gr_message_strobe()
+{
+ d_finished = true;
+ d_thread->interrupt();
+ d_thread->join();
+}
+
+void gr_message_strobe::run(){
+ while(!d_finished) {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(d_period_ms));
+ if(d_finished){ return; }
+
+ message_port_pub( pmt::mp("strobe"), d_msg );
+ }
+}
diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.h b/gnuradio-core/src/lib/general/gr_message_strobe.h
new file mode 100644
index 000000000..89046ffc0
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_message_strobe.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_GR_MESSAGE_STROBE_H
+#define INCLUDED_GR_MESSAGE_STROBE_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+
+class gr_message_strobe;
+typedef boost::shared_ptr<gr_message_strobe> gr_message_strobe_sptr;
+
+GR_CORE_API gr_message_strobe_sptr gr_make_message_strobe (pmt::pmt_t msg, float period_ms);
+
+/*!
+ * \brief Send message at defined interval
+ * \ingroup msg_blk
+ */
+class GR_CORE_API gr_message_strobe : public gr_block
+{
+ private:
+ friend GR_CORE_API gr_message_strobe_sptr
+ gr_make_message_strobe(pmt::pmt_t msg, float period_ms);
+
+ boost::shared_ptr<boost::thread> d_thread;
+ bool d_finished;
+ float d_period_ms;
+ pmt::pmt_t d_msg;
+
+ void run();
+
+ protected:
+ gr_message_strobe (pmt::pmt_t msg, float period_ms);
+
+ public:
+ ~gr_message_strobe ();
+
+ void set_msg(pmt::pmt_t msg){ d_msg = msg; }
+};
+
+#endif /* INCLUDED_GR_MESSAGE_STROBE_H */
diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.i b/gnuradio-core/src/lib/general/gr_message_strobe.i
new file mode 100644
index 000000000..490aa8e8a
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_message_strobe.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,message_strobe);
+
+%{
+#include <gr_message_strobe.h>
+%}
+
+%include "gr_message_strobe.h"
+
diff --git a/gnuradio-core/src/lib/general/gr_nop.cc b/gnuradio-core/src/lib/general/gr_nop.cc
index ca5983c39..edfe1d76d 100644
--- a/gnuradio-core/src/lib/general/gr_nop.cc
+++ b/gnuradio-core/src/lib/general/gr_nop.cc
@@ -40,7 +40,8 @@ gr_nop::gr_nop (size_t sizeof_stream_item)
d_nmsgs_recvd(0)
{
// Arrange to have count_received_msgs called when messages are received.
- set_msg_handler(boost::bind(&gr_nop::count_received_msgs, this, _1));
+ message_port_register_in(pmt::mp("port"));
+ set_msg_handler(pmt::mp("port"), boost::bind(&gr_nop::count_received_msgs, this, _1));
}
// Trivial message handler that just counts them.
diff --git a/gnuradio-core/src/lib/general/gr_skiphead.cc b/gnuradio-core/src/lib/general/gr_skiphead.cc
index c887376e4..7b441bea9 100644
--- a/gnuradio-core/src/lib/general/gr_skiphead.cc
+++ b/gnuradio-core/src/lib/general/gr_skiphead.cc
@@ -43,14 +43,14 @@ gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip)
int
gr_skiphead::general_work(int noutput_items,
- gr_vector_int &ninput_items_ignored,
+ gr_vector_int &ninput_items_,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const char *in = (const char *) input_items[0];
char *out = (char *) output_items[0];
- int ninput_items = noutput_items; // we've got at least this many input items
+ int ninput_items = std::min(ninput_items_[0], noutput_items);
int ii = 0; // input index
while (ii < ninput_items){
diff --git a/gnuradio-core/src/lib/general/gri_control_loop.cc b/gnuradio-core/src/lib/general/gri_control_loop.cc
index 5a93737f9..bb3c4a326 100644
--- a/gnuradio-core/src/lib/general/gri_control_loop.cc
+++ b/gnuradio-core/src/lib/general/gri_control_loop.cc
@@ -144,6 +144,17 @@ gri_control_loop::set_phase(float phase)
d_phase += M_TWOPI;
}
+void
+gri_control_loop::set_max_freq(float freq)
+{
+ d_max_freq = freq;
+}
+
+void
+gri_control_loop::set_min_freq(float freq)
+{
+ d_min_freq = freq;
+}
/*******************************************************************
GET FUNCTIONS
@@ -185,3 +196,15 @@ gri_control_loop::get_phase() const
{
return d_phase;
}
+
+float
+gri_control_loop::get_max_freq() const
+{
+ return d_max_freq;
+}
+
+float
+gri_control_loop::get_min_freq() const
+{
+ return d_min_freq;
+}
diff --git a/gnuradio-core/src/lib/general/gri_control_loop.h b/gnuradio-core/src/lib/general/gri_control_loop.h
index df260d2cf..304857ac7 100644
--- a/gnuradio-core/src/lib/general/gri_control_loop.h
+++ b/gnuradio-core/src/lib/general/gri_control_loop.h
@@ -141,9 +141,9 @@ class GR_CORE_API gri_control_loop
void set_beta(float beta);
/*!
- * \brief Set the Costas loop's frequency.
+ * \brief Set the control loop's frequency.
*
- * Set's the Costas Loop's frequency. While this is normally updated by the
+ * Set's the control loop's frequency. While this is normally updated by the
* inner loop of the algorithm, it could be useful to manually initialize,
* set, or reset this under certain circumstances.
*
@@ -153,9 +153,9 @@ class GR_CORE_API gri_control_loop
void set_frequency(float freq);
/*!
- * \brief Set the Costas loop's phase.
+ * \brief Set the control loop's phase.
*
- * Set's the Costas Loop's phase. While this is normally updated by the
+ * Set's the control loop's phase. While this is normally updated by the
* inner loop of the algorithm, it could be useful to manually initialize,
* set, or reset this under certain circumstances.
*
@@ -164,6 +164,23 @@ class GR_CORE_API gri_control_loop
*/
void set_phase(float phase);
+ /*!
+ * \brief Set the control loop's maximum frequency.
+ *
+ * Set the maximum frequency the control loop can track.
+ *
+ * \param freq (float) new max frequency
+ */
+ void set_max_freq(float freq);
+
+ /*!
+ * \brief Set the control loop's minimum frequency.
+ *
+ * Set the minimum frequency the control loop can track.
+ *
+ * \param freq (float) new min frequency
+ */
+ void set_min_freq(float freq);
/*******************************************************************
GET FUNCTIONS
@@ -190,14 +207,24 @@ class GR_CORE_API gri_control_loop
float get_beta() const;
/*!
- * \brief Get the Costas loop's frequency estimate
+ * \brief Get the control loop's frequency estimate
*/
float get_frequency() const;
/*!
- * \brief Get the Costas loop's phase estimate
+ * \brief Get the control loop's phase estimate
*/
float get_phase() const;
+
+ /*!
+ * \brief Get the control loop's maximum frequency.
+ */
+ float get_max_freq() const;
+
+ /*!
+ * \brief Get the control loop's minimum frequency.
+ */
+ float get_min_freq() const;
};
#endif /* GRI_CONTROL_LOOP */
diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt
index 3dea13396..7041f2820 100644
--- a/gnuradio-core/src/lib/io/CMakeLists.txt
+++ b/gnuradio-core/src/lib/io/CMakeLists.txt
@@ -38,6 +38,7 @@ list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.cc
${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.cc
${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.cc
)
########################################################################
@@ -59,6 +60,7 @@ install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.h
${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.h
${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
COMPONENT "core_devel"
)
@@ -85,9 +87,11 @@ set(gr_core_io_triple_threats
gr_file_source
gr_file_descriptor_sink
gr_file_descriptor_source
+ gr_message_debug
gr_message_sink
gr_message_source
gr_message_burst_source
+ gr_pdu_to_tagged_stream
microtune_xxxx_eval_board
microtune_4702_eval_board
microtune_4937_eval_board
@@ -98,6 +102,7 @@ set(gr_core_io_triple_threats
gr_wavfile_source
gr_wavfile_sink
gr_tagged_file_sink
+ gr_tagged_stream_to_pdu
)
foreach(file_tt ${gr_core_io_triple_threats})
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc
new file mode 100644
index 000000000..d98954576
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_debug.cc
@@ -0,0 +1,64 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_message_debug.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+
+// public constructor that returns a shared_ptr
+
+gr_message_debug_sptr
+gr_make_message_debug ()
+{
+ return gnuradio::get_initial_sptr(new gr_message_debug());
+}
+
+void gr_message_debug::print(pmt::pmt_t msg){
+ std::cout << "******* MESSAGE DEBUG PRINT ********\n";
+ pmt::pmt_print(msg);
+ std::cout << "************************************\n";
+}
+
+
+gr_message_debug::gr_message_debug ()
+ : gr_block("message_debug",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(0, 0, 0))
+{
+ message_port_register_in(pmt::mp("print"));
+ set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1));
+}
+
+gr_message_debug::~gr_message_debug()
+{
+}
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h
new file mode 100644
index 000000000..120694a91
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_debug.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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.
+ */
+
+#ifndef INCLUDED_GR_MESSAGE_DEBUG_H
+#define INCLUDED_GR_MESSAGE_DEBUG_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+
+class gr_message_debug;
+typedef boost::shared_ptr<gr_message_debug> gr_message_debug_sptr;
+
+GR_CORE_API gr_message_debug_sptr gr_make_message_debug ();
+
+/*!
+ * \brief Print received messages to stdout
+ * \ingroup sink_blk
+ */
+class GR_CORE_API gr_message_debug : public gr_block
+{
+ private:
+ friend GR_CORE_API gr_message_debug_sptr
+ gr_make_message_debug();
+
+ void print(pmt::pmt_t msg);
+
+ protected:
+ gr_message_debug ();
+
+ public:
+ ~gr_message_debug ();
+};
+
+#endif /* INCLUDED_GR_MESSAGE_DEBUG_H */
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.i b/gnuradio-core/src/lib/io/gr_message_debug.i
new file mode 100644
index 000000000..65d3bfc4a
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_debug.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,message_debug);
+
+%{
+#include <gr_message_debug.h>
+%}
+
+%include "gr_message_debug.h"
+
diff --git a/gnuradio-core/src/lib/io/gr_pdu.cc b/gnuradio-core/src/lib/io/gr_pdu.cc
new file mode 100644
index 000000000..f33eed0a3
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu.cc
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_pdu.h>
+
+size_t
+gr_pdu_itemsize(gr_pdu_vector_type type){
+ switch(type){
+ case BYTE:
+ return 1;
+ case FLOAT:
+ return sizeof(float);
+ case COMPLEX:
+ return sizeof(gr_complex);
+ default:
+ throw std::runtime_error("bad type!");
+ }
+}
+
+bool
+gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){
+ switch(type){
+ case BYTE:
+ return pmt::pmt_is_u8vector(v);
+ case FLOAT:
+ return pmt::pmt_is_f32vector(v);
+ case COMPLEX:
+ return pmt::pmt_is_c32vector(v);
+ default:
+ throw std::runtime_error("bad type!");
+ }
+}
+
+pmt::pmt_t
+gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){
+ switch(type){
+ case BYTE:
+ return pmt::pmt_init_u8vector(items, buf);
+ case FLOAT:
+ return pmt::pmt_init_f32vector(items, (const float*)buf);
+ case COMPLEX:
+ return pmt::pmt_init_c32vector(items, (const gr_complex*)buf);
+ default:
+ throw std::runtime_error("bad type!");
+ }
+}
diff --git a/gnuradio-core/src/lib/io/gr_pdu.h b/gnuradio-core/src/lib/io/gr_pdu.h
new file mode 100644
index 000000000..67519c89d
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef GR_PDU_H
+#define GR_PDU_H
+
+#include <gr_complex.h>
+#include <gruel/pmt.h>
+
+#define pdu_port_id pmt::mp("pdus")
+#define pdu_length_tag pmt::mp("pdu_length")
+
+enum gr_pdu_vector_type { BYTE, FLOAT, COMPLEX };
+
+size_t gr_pdu_itemsize(gr_pdu_vector_type type);
+bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v);
+pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items);
+
+#endif
diff --git a/gnuradio-core/src/lib/io/gr_pdu.i b/gnuradio-core/src/lib/io/gr_pdu.i
new file mode 100644
index 000000000..7cb3c62c7
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+%{
+#include <gr_pdu.h>
+%}
+
+enum gr_pdu_vector_type { BYTE, FLOAT, COMPLEX };
+
+
+
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc
new file mode 100644
index 000000000..5c319dc39
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc
@@ -0,0 +1,132 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_pdu_to_tagged_stream.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+
+
+// public constructor that returns a shared_ptr
+
+gr_pdu_to_tagged_stream_sptr
+gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t)
+{
+ return gnuradio::get_initial_sptr(new gr_pdu_to_tagged_stream(t));
+}
+
+gr_pdu_to_tagged_stream::gr_pdu_to_tagged_stream (gr_pdu_vector_type t)
+ : gr_sync_block("pdu_to_tagged_stream",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, gr_pdu_itemsize(t))),
+ d_vectortype(t), d_itemsize(gr_pdu_itemsize(t))
+{
+ message_port_register_in(pdu_port_id);
+}
+
+gr_pdu_to_tagged_stream::~gr_pdu_to_tagged_stream()
+{
+}
+
+int
+gr_pdu_to_tagged_stream::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ char *out = (char *) output_items[0];
+ int nout = 0;
+
+ // if we have remaining output, send it
+ if(d_remain.size() > 0){
+ nout = std::min((size_t)d_remain.size()/d_itemsize, (size_t)noutput_items);
+ memcpy(out, &d_remain[0], nout*d_itemsize);
+ d_remain.erase( d_remain.begin(), d_remain.begin()+nout);
+ noutput_items -= nout;
+ out += nout*d_itemsize;
+ }
+
+ // if we have space for at least one item output as much as we can
+ if(noutput_items > 0){
+
+ // grab a message if one exists
+ //pmt::pmt_t msg( delete_head_nowait( pdu_port_id ) );
+ pmt::pmt_t msg( delete_head_blocking( pdu_port_id ) );
+ if(msg.get() == NULL ){
+ return nout;
+ }
+
+ // make sure type is valid
+ if(!pmt::pmt_is_pair(msg)){
+ throw std::runtime_error("received a malformed pdu message!");
+ }
+
+// printf("got a msg\n");
+// pmt::pmt_print(msg);
+
+ // grab the components of the pdu message
+ pmt::pmt_t meta(pmt::pmt_car(msg)); // make sure this is NIL || Dict ?
+ pmt::pmt_t vect(pmt::pmt_cdr(msg)); // make sure this is a vector?
+
+ // compute offset for output tag
+ uint64_t offset = nitems_written(0) + nout;
+
+ // add a tag for pdu length
+ add_item_tag(0, offset, pdu_length_tag, pmt::pmt_from_long( pmt::pmt_length(vect) ), pmt::mp(alias()));
+
+ // if we recieved metadata add it as tags
+ if( !pmt_eq(meta, pmt::PMT_NIL) ){
+ pmt::pmt_t pair(pmt::pmt_dict_keys( meta ));
+ while( !pmt_eq(pair, pmt::PMT_NIL) ){
+ pmt::pmt_t k(pmt::pmt_cdr(pair));
+ pmt::pmt_t v(pmt::pmt_dict_ref(meta, k, pmt::PMT_NIL));
+ add_item_tag(0, offset, k, v, pmt::mp(alias()));
+ }
+ }
+
+ // copy vector output
+ size_t ncopy = std::min((size_t)noutput_items, (size_t)pmt::pmt_length(vect));
+ size_t nsave = pmt::pmt_length(vect) - ncopy;
+
+ // copy output
+ size_t io(0);
+ nout += ncopy;
+ memcpy(out, pmt_uniform_vector_elements(vect,io), ncopy*d_itemsize);
+
+ // save leftover items if needed for next work call
+ if(nsave > 0){
+ d_remain.resize(nsave*d_itemsize, 0);
+ memcpy(&d_remain[0], pmt_uniform_vector_elements(vect,ncopy), nsave*d_itemsize);
+ }
+
+ }
+
+ return nout;
+}
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h
new file mode 100644
index 000000000..3105a3d38
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_GR_PDU_TO_TAGGED_STREAM_H
+#define INCLUDED_GR_PDU_TO_TAGGED_STREAM_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gr_pdu.h>
+
+class gr_pdu_to_tagged_stream;
+typedef boost::shared_ptr<gr_pdu_to_tagged_stream> gr_pdu_to_tagged_stream_sptr;
+
+GR_CORE_API gr_pdu_to_tagged_stream_sptr gr_make_pdu_to_tagged_stream (gr_pdu_vector_type t);
+
+/*!
+ * \brief Turn received messages into a stream
+ * \ingroup source_blk
+ */
+class GR_CORE_API gr_pdu_to_tagged_stream : public gr_sync_block
+{
+ private:
+ gr_pdu_vector_type d_vectortype;
+ size_t d_itemsize;
+ std::vector<uint8_t> d_remain;
+
+ friend GR_CORE_API gr_pdu_to_tagged_stream_sptr
+ gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t);
+
+ protected:
+ gr_pdu_to_tagged_stream (gr_pdu_vector_type t);
+
+ public:
+ ~gr_pdu_to_tagged_stream ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+};
+
+#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i
new file mode 100644
index 000000000..ec760b309
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,pdu_to_tagged_stream);
+
+%{
+#include <gr_pdu_to_tagged_stream.h>
+%}
+
+%include <gr_pdu_to_tagged_stream.h>
+
+
diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc
new file mode 100644
index 000000000..8211b7672
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc
@@ -0,0 +1,137 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_tagged_stream_to_pdu.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+
+// public constructor that returns a shared_ptr
+
+gr_tagged_stream_to_pdu_sptr
+gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t)
+{
+ return gnuradio::get_initial_sptr(new gr_tagged_stream_to_pdu(t));
+}
+
+gr_tagged_stream_to_pdu::gr_tagged_stream_to_pdu (gr_pdu_vector_type t)
+ : gr_sync_block("tagged_stream_to_pdu",
+ gr_make_io_signature(1, 1, gr_pdu_itemsize(t)),
+ gr_make_io_signature(0, 0, 0)),
+ d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)), d_inpdu(false),
+ d_pdu_meta(pmt::PMT_NIL), d_pdu_vector(pmt::PMT_NIL)
+{
+ message_port_register_out(pdu_port_id);
+}
+
+gr_tagged_stream_to_pdu::~gr_tagged_stream_to_pdu()
+{
+ printf("destructor running\n");
+}
+
+int
+gr_tagged_stream_to_pdu::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const uint8_t *in = (const uint8_t*) input_items[0];
+ uint64_t abs_N = nitems_read(0);
+
+ // if we are not in a pdu already, start a new one
+ if(!d_inpdu){
+ get_tags_in_range(d_tags, 0, abs_N, abs_N+1);
+ bool found_length_tag(false);
+ for(d_tags_itr = d_tags.begin(); (d_tags_itr != d_tags.end()) && (!found_length_tag); d_tags_itr++){
+ if( pmt::pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){
+ if( (*d_tags_itr).offset != abs_N ){
+ throw std::runtime_error("expected next pdu length tag on a different item...");
+ }
+ found_length_tag = true;
+ d_pdu_length = pmt::pmt_to_long( (*d_tags_itr).value );
+ d_pdu_remain = d_pdu_length;
+ d_pdu_meta = pmt::pmt_make_dict();
+ break;
+ } // if have length tag
+ } // iter over tags
+ if(!found_length_tag){
+ throw std::runtime_error("tagged stream does not contain a pdu_length tag!");
+ }
+ }
+
+ size_t ncopy = std::min((size_t)noutput_items, d_pdu_remain);
+
+ // copy any tags in this range into our meta object
+ get_tags_in_range(d_tags, 0, abs_N, abs_N+ncopy);
+ for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++){
+ if( ! pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){
+ d_pdu_meta = pmt_dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value);
+ }
+ }
+
+ // copy samples for this vector into either a pmt or our save buffer
+ if(ncopy == d_pdu_remain){ // we will send this pdu
+ if(d_save.size() == 0){
+ d_pdu_vector = gr_pdu_make_vector(d_vectortype, in, ncopy);
+ send_message();
+ } else {
+ size_t oldsize = d_save.size();
+ d_save.resize((oldsize + ncopy)*d_itemsize, 0);
+ memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize );
+ d_pdu_vector = gr_pdu_make_vector(d_vectortype, &d_save[0], d_pdu_length);
+ send_message();
+ d_save.clear();
+ }
+ } else {
+ d_inpdu = true;
+ size_t oldsize = d_save.size();
+ d_save.resize( (oldsize+ncopy)*d_itemsize );
+ memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize );
+ d_pdu_remain -= ncopy;
+ }
+
+ return ncopy;
+}
+
+void gr_tagged_stream_to_pdu::send_message(){
+
+ if(pmt::pmt_length(d_pdu_vector) != d_pdu_length){
+ throw std::runtime_error("msg length not correct");
+ }
+
+ pmt::pmt_t msg = pmt::pmt_cons( d_pdu_meta, d_pdu_vector );
+ message_port_pub( pdu_port_id, msg );
+
+ d_pdu_meta = pmt::PMT_NIL;
+ d_pdu_vector = pmt::PMT_NIL;
+ d_pdu_length = 0;
+ d_pdu_remain = 0;
+ d_inpdu = false;
+}
diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h
new file mode 100644
index 000000000..c3fff3581
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_GR_TAGGED_STREAM_TO_PDU_H
+#define INCLUDED_GR_TAGGED_STREAM_TO_PDU_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gr_pdu.h>
+
+class gr_tagged_stream_to_pdu;
+typedef boost::shared_ptr<gr_tagged_stream_to_pdu> gr_tagged_stream_to_pdu_sptr;
+
+GR_CORE_API gr_tagged_stream_to_pdu_sptr gr_make_tagged_stream_to_pdu (gr_pdu_vector_type t);
+
+/*!
+ * \brief Turn received messages into a stream
+ * \ingroup source_blk
+ */
+class GR_CORE_API gr_tagged_stream_to_pdu : public gr_sync_block
+{
+ private:
+ gr_pdu_vector_type d_vectortype;
+ size_t d_itemsize;
+
+ std::vector<uint8_t> d_save;
+
+ std::vector<gr_tag_t> d_tags;
+ std::vector<gr_tag_t>::iterator d_tags_itr;
+
+ bool d_inpdu;
+
+ size_t d_pdu_length;
+ size_t d_pdu_remain;
+ pmt::pmt_t d_pdu_meta;
+ pmt::pmt_t d_pdu_vector;
+
+ friend GR_CORE_API gr_tagged_stream_to_pdu_sptr
+ gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t);
+
+ protected:
+ gr_tagged_stream_to_pdu (gr_pdu_vector_type t);
+
+ public:
+ ~gr_tagged_stream_to_pdu ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ void send_message();
+
+};
+
+#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */
diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i
new file mode 100644
index 000000000..f12987b74
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,tagged_stream_to_pdu);
+
+%{
+#include <gr_tagged_stream_to_pdu.h>
+%}
+
+%include <gr_tagged_stream_to_pdu.h>
+
+
diff --git a/gnuradio-core/src/lib/io/gr_udp_source.cc b/gnuradio-core/src/lib/io/gr_udp_source.cc
index af41159ee..eca8e89d0 100644
--- a/gnuradio-core/src/lib/io/gr_udp_source.cc
+++ b/gnuradio-core/src/lib/io/gr_udp_source.cc
@@ -269,8 +269,9 @@ gr_udp_source::work (int noutput_items,
else if(r == 0 ) { // timed out
if( d_wait ) {
// Allow boost thread interrupt, then try again
- boost::this_thread::interruption_point();
- continue;
+ //boost::this_thread::interruption_point();
+ //continue;
+ return 0;
}
else
return -1;
@@ -294,8 +295,9 @@ gr_udp_source::work (int noutput_items,
if( d_wait ) {
// Allow boost thread interrupt, then try again
- boost::this_thread::interruption_point();
- continue;
+ //boost::this_thread::interruption_point();
+ //continue;
+ return 0;
}
else
return -1;
diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i
index 5cd352905..871ce1356 100644
--- a/gnuradio-core/src/lib/io/io.i
+++ b/gnuradio-core/src/lib/io/io.i
@@ -45,6 +45,10 @@
#include <gr_wavfile_sink.h>
#include <gr_wavfile_source.h>
#include <gr_tagged_file_sink.h>
+#include <gr_pdu_to_tagged_stream.h>
+#include <gr_tagged_stream_to_pdu.h>
+#include <gr_message_debug.h>
+#include <gr_pdu.h>
%}
%include "gr_file_sink_base.i"
@@ -67,4 +71,8 @@
%include "gr_wavfile_sink.i"
%include "gr_wavfile_source.i"
%include "gr_tagged_file_sink.i"
+%include "gr_pdu_to_tagged_stream.i"
+%include "gr_tagged_stream_to_pdu.i"
+%include "gr_message_debug.i"
+%include "gr_pdu.i"
diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt
index 5f3672dde..70938a0f1 100644
--- a/gnuradio-core/src/lib/runtime/CMakeLists.txt
+++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt
@@ -54,6 +54,7 @@ list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/gr_block.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.cc
@@ -116,6 +117,7 @@ install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/gr_block.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.h
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc
index d7263b92d..69f2e09f9 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,7 +25,10 @@
#endif
#include <gr_basic_block.h>
+#include <gr_block_registry.h>
#include <stdexcept>
+#include <sstream>
+#include <iostream>
using namespace pmt;
@@ -45,14 +48,19 @@ gr_basic_block::gr_basic_block(const std::string &name,
d_input_signature(input_signature),
d_output_signature(output_signature),
d_unique_id(s_next_id++),
- d_color(WHITE)
+ d_symbolic_id(global_block_registry.block_register(this)),
+ d_symbol_name(global_block_registry.register_symbolic_name(this)),
+ d_color(WHITE),
+ message_subscribers(pmt::pmt_make_dict())
{
+ mutex.unlock();
s_ncurrently_allocated++;
}
gr_basic_block::~gr_basic_block()
{
s_ncurrently_allocated--;
+ global_block_registry.block_unregister(this);
}
gr_basic_block_sptr
@@ -60,3 +68,117 @@ gr_basic_block::to_basic_block()
{
return shared_from_this();
}
+
+void
+gr_basic_block::set_block_alias(std::string name)
+{
+ global_block_registry.register_symbolic_name(this, name);
+}
+
+// ** Message passing interface **
+
+// - register a new input message port
+void gr_basic_block::message_port_register_in(pmt::pmt_t port_id){
+ msg_queue[port_id] = msg_queue_t();
+ msg_queue_ready[port_id] = boost::shared_ptr<boost::condition_variable>(new boost::condition_variable());
+ }
+
+// - register a new output message port
+void gr_basic_block::message_port_register_out(pmt::pmt_t port_id){
+ if(!pmt::pmt_is_symbol(port_id)){ throw std::runtime_error("bad port id"); }
+ if(pmt::pmt_dict_has_key(message_subscribers, port_id)){ throw std::runtime_error("port already in use"); }
+ message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL);
+ }
+
+// - publish a message on a message port
+void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg){
+ if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ throw std::runtime_error("port does not exist"); }
+ pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+ // iterate through subscribers on port
+ while( pmt::pmt_is_pair(currlist) ){
+ pmt::pmt_t target = pmt::pmt_car(currlist);
+
+ pmt::pmt_t block = pmt::pmt_car(target);
+ pmt::pmt_t port = pmt::pmt_cdr(target);
+
+ currlist = pmt::pmt_cdr(currlist);
+ gr_basic_block_sptr blk = global_block_registry.block_lookup(block);
+ //blk->post(msg);
+ blk->post(port, msg);
+ }
+ }
+
+// - subscribe to a message port
+void gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){
+ if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){
+ std::stringstream ss;
+ ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl;
+ throw std::runtime_error(ss.str());
+ }
+ pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+ message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target));
+ }
+
+void gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){
+ if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){
+ std::stringstream ss;
+ ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl;
+ throw std::runtime_error(ss.str());
+ }
+ pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+ message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target));
+ }
+
+void
+gr_basic_block::_post(pmt_t which_port, pmt_t msg)
+{
+ insert_tail(which_port, msg);
+}
+
+void
+gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg)
+{
+ gruel::scoped_lock guard(mutex);
+
+ if( (msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())){
+ std::cout << "target port = " << pmt::pmt_symbol_to_string(which_port) << std::endl;
+ throw std::runtime_error("attempted to insert_tail on invalid queue!");
+ }
+
+ msg_queue[which_port].push_back(msg);
+ msg_queue_ready[which_port]->notify_one();
+
+ // wake up thread if BLKD_IN or BLKD_OUT
+ global_block_registry.notify_blk(alias());
+}
+
+pmt_t
+gr_basic_block::delete_head_nowait(pmt::pmt_t which_port)
+{
+ gruel::scoped_lock guard(mutex);
+
+ if (empty_p(which_port)){
+ return pmt::pmt_t();
+ }
+
+ pmt_t m(msg_queue[which_port].front());
+ msg_queue[which_port].pop_front();
+
+ return m;
+}
+
+pmt_t
+gr_basic_block::delete_head_blocking(pmt::pmt_t which_port)
+{
+ gruel::scoped_lock guard(mutex);
+
+ while (empty_p(which_port)){
+ msg_queue_ready[which_port]->wait(guard);
+ }
+
+ pmt_t m(msg_queue[which_port].front());
+ msg_queue[which_port].pop_front();
+ return m;
+}
+
+
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h
index 4d03b878e..e0fd5d2af 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h
@@ -30,6 +30,12 @@
#include <boost/function.hpp>
#include <gr_msg_accepter.h>
#include <string>
+#include <deque>
+#include <map>
+#include <gr_io_signature.h>
+#include <gruel/thread.h>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition_variable.hpp>
/*!
* \brief The abstract base class for all signal processing blocks.
@@ -53,13 +59,25 @@ private:
* The thread-safety guarantees mentioned in set_msg_handler are implemented
* by the callers of this method.
*/
- void dispatch_msg(pmt::pmt_t msg)
+ void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
{
- if (d_msg_handler) // Is there a handler?
- d_msg_handler(msg); // Yes, invoke it.
+ // AA Update this
+ if (d_msg_handlers.find(which_port) != d_msg_handlers.end()) // Is there a handler?
+ d_msg_handlers[which_port](msg); // Yes, invoke it.
};
- msg_handler_t d_msg_handler;
+ //msg_handler_t d_msg_handler;
+ typedef std::map<pmt::pmt_t , msg_handler_t, pmt::pmt_comperator> d_msg_handlers_t;
+ d_msg_handlers_t d_msg_handlers;
+
+ typedef std::deque<pmt::pmt_t> msg_queue_t;
+ typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator> msg_queue_map_t;
+ msg_queue_map_t msg_queue;
+// boost::condition_variable msg_queue_ready;
+ std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::pmt_comperator> msg_queue_ready;
+
+ gruel::mutex mutex; //< protects all vars
+
protected:
friend class gr_flowgraph;
@@ -72,6 +90,9 @@ protected:
gr_io_signature_sptr d_input_signature;
gr_io_signature_sptr d_output_signature;
long d_unique_id;
+ long d_symbolic_id;
+ std::string d_symbol_name;
+ std::string d_symbol_alias;
vcolor d_color;
gr_basic_block(void){} //allows pure virtual interface sub-classes
@@ -97,13 +118,67 @@ protected:
void set_color(vcolor color) { d_color = color; }
vcolor color() const { return d_color; }
+ // Message passing interface
+ pmt::pmt_t message_subscribers;
+
public:
virtual ~gr_basic_block();
long unique_id() const { return d_unique_id; }
+ long symbolic_id() const { return d_symbolic_id; }
std::string name() const { return d_name; }
+ std::string symbol_name() const { return d_symbol_name; }
gr_io_signature_sptr input_signature() const { return d_input_signature; }
gr_io_signature_sptr output_signature() const { return d_output_signature; }
gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion
+ bool alias_set() { return !d_symbol_alias.empty(); }
+ std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
+ pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); }
+ void set_block_alias(std::string name);
+
+ // ** Message passing interface **
+ void message_port_register_in(pmt::pmt_t port_id);
+ void message_port_register_out(pmt::pmt_t port_id);
+ void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);
+ void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target);
+ void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target);
+
+ /*!
+ * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
+ */
+ void _post(pmt::pmt_t which_port, pmt::pmt_t msg);
+
+ //! is the queue empty?
+ //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); }
+ bool empty_p(pmt::pmt_t which_port) {
+ if(msg_queue.find(which_port) == msg_queue.end())
+ throw std::runtime_error("port does not exist!");
+ return msg_queue[which_port].empty();
+ }
+ bool empty_p() {
+ bool rv = true;
+ BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); }
+ return rv;
+ }
+
+ //| Acquires and release the mutex
+ void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg);
+ /*!
+ * \returns returns pmt at head of queue or pmt_t() if empty.
+ */
+ pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port);
+
+ /*!
+ * \returns returns pmt at head of queue or pmt_t() if empty.
+ */
+ pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port);
+
+ msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){
+ return msg_queue[which_port].begin();
+ }
+ void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){
+ msg_queue[which_port].erase(it);
+ }
+
/*!
* \brief Confirm that ninputs and noutputs is an acceptable combination.
@@ -146,8 +221,13 @@ public:
* If the block inherits from gr_hier_block2, the runtime system will
* ensure that no reentrant calls are made to msg_handler.
*/
- template <typename T> void set_msg_handler(T msg_handler){
- d_msg_handler = msg_handler_t(msg_handler);
+ //template <typename T> void set_msg_handler(T msg_handler){
+ // d_msg_handler = msg_handler_t(msg_handler);
+ //}
+ template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){
+ if(msg_queue.find(which_port) == msg_queue.end()){
+ throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); }
+ d_msg_handlers[which_port] = msg_handler_t(msg_handler);
}
};
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i
index e43cc114c..d6d6c3d16 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i
@@ -23,6 +23,8 @@
class gr_basic_block;
typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr;
%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>;
+%include "pmt_swig.i"
+using namespace pmt;
// support vectors of these...
namespace std {
@@ -37,11 +39,15 @@ protected:
public:
virtual ~gr_basic_block();
std::string name() const;
+ std::string symbol_name() const;
gr_io_signature_sptr input_signature() const;
gr_io_signature_sptr output_signature() const;
long unique_id() const;
gr_basic_block_sptr to_basic_block();
bool check_topology (int ninputs, int noutputs);
+ std::string alias();
+ void set_block_alias(std::string name);
+ void _post(pmt_t which_port, pmt_t msg);
};
%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated;
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index 9a5255a93..43aebf0bf 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -28,6 +28,7 @@
#include <gr_block_detail.h>
#include <stdexcept>
#include <iostream>
+#include <gr_block_registry.h>
gr_block::gr_block (const std::string &name,
gr_io_signature_sptr input_signature,
@@ -40,12 +41,18 @@ gr_block::gr_block (const std::string &name,
d_relative_rate (1.0),
d_history(1),
d_fixed_rate(false),
- d_tag_propagation_policy(TPP_ALL_TO_ALL)
+ d_max_noutput_items_set(false),
+ d_max_noutput_items(0),
+ d_tag_propagation_policy(TPP_ALL_TO_ALL),
+ d_max_output_buffer(std::max(output_signature->max_streams(),1), -1),
+ d_min_output_buffer(std::max(output_signature->max_streams(),1), -1)
{
+ global_block_registry.register_primitive(alias(), this);
}
gr_block::~gr_block ()
{
+ global_block_registry.unregister_primitive(alias());
}
// stub implementation: 1:1
@@ -208,6 +215,35 @@ gr_block::set_tag_propagation_policy(tag_propagation_policy_t p)
d_tag_propagation_policy = p;
}
+
+int
+gr_block::max_noutput_items()
+{
+ return d_max_noutput_items;
+}
+
+void
+gr_block::set_max_noutput_items(int m)
+{
+ if(m <= 0)
+ throw std::runtime_error("gr_block::set_max_noutput_items: value for max_noutput_items must be greater than 0.\n");
+
+ d_max_noutput_items = m;
+ d_max_noutput_items_set = true;
+}
+
+void
+gr_block::unset_max_noutput_items()
+{
+ d_max_noutput_items_set = false;
+}
+
+bool
+gr_block::is_set_max_noutput_items()
+{
+ return d_max_noutput_items_set;
+}
+
std::ostream&
operator << (std::ostream& os, const gr_block *m)
{
@@ -215,3 +251,12 @@ operator << (std::ostream& os, const gr_block *m)
return os;
}
+int
+gr_block::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ throw std::runtime_error("gr_block::general_work() not implemented");
+ return 0;
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index 71ac8eee6..57e3fda90 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -124,7 +124,7 @@ class GR_CORE_API gr_block : public gr_basic_block {
virtual int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items) = 0;
+ gr_vector_void_star &output_items);
/*!
* \brief Called to enable drivers, etc for i/o devices.
@@ -251,6 +251,113 @@ class GR_CORE_API gr_block : public gr_basic_block {
*/
void set_tag_propagation_policy(tag_propagation_policy_t p);
+ /*!
+ * \brief Return the maximum number of output items this block will
+ * handle during a call to work.
+ */
+ int max_noutput_items();
+
+ /*!
+ * \brief Set the maximum number of ouput items htis block will
+ * handle during a call to work.
+ *
+ * \param m the maximum noutput_items this block will handle.
+ */
+ void set_max_noutput_items(int m);
+
+ /*!
+ * \brief Clear the switch for using the max_noutput_items value of this block.
+ *
+ * When is_set_max_noutput_items() returns 'true', the scheduler
+ * will use the value returned by max_noutput_items() to limit the
+ * size of the number of items possible for this block's work
+ * function. If is_set_max_notput_items() returns 'false', then the
+ * scheduler ignores the internal value and uses the value set
+ * globally in the top_block.
+ *
+ * Use this value to clear the 'is_set' flag so the scheduler will
+ * ignore this. Use the set_max_noutput_items(m) call to both set a
+ * new value for max_noutput_items and to reenable its use in the
+ * scheduler.
+ */
+ void unset_max_noutput_items();
+
+ /*!
+ * \brief Ask the block if the flag is or is not set to use the
+ * internal value of max_noutput_items during a call to work.
+ */
+ bool is_set_max_noutput_items();
+
+ /*
+ * Used to expand the vectors that hold the min/max buffer sizes.
+ *
+ * Specifically, when -1 is used, the vectors are just initialized
+ * with 1 value; this is used by the flat_flowgraph to expand when
+ * required to add a new value for new ports on these blocks.
+ */
+ void expand_minmax_buffer(int port) {
+ if((size_t)port >= d_max_output_buffer.size())
+ set_max_output_buffer(port, -1);
+ if((size_t)port >= d_min_output_buffer.size())
+ set_min_output_buffer(port, -1);
+ }
+
+ /*!
+ * \brief Returns max buffer size on output port \p i.
+ */
+ long max_output_buffer(size_t i) {
+ if(i >= d_max_output_buffer.size())
+ throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range.");
+ return d_max_output_buffer[i];
+ }
+
+ /*!
+ * \brief Sets max buffer size on all output ports.
+ */
+ void set_max_output_buffer(long max_output_buffer) {
+ for(int i = 0; i < output_signature()->max_streams(); i++) {
+ set_max_output_buffer(i, max_output_buffer);
+ }
+ }
+
+ /*!
+ * \brief Sets max buffer size on output port \p port.
+ */
+ void set_max_output_buffer(int port, long max_output_buffer) {
+ if((size_t)port >= d_max_output_buffer.size())
+ d_max_output_buffer.push_back(max_output_buffer);
+ else
+ d_max_output_buffer[port] = max_output_buffer;
+ }
+
+ /*!
+ * \brief Returns min buffer size on output port \p i.
+ */
+ long min_output_buffer(size_t i) {
+ if(i >= d_min_output_buffer.size())
+ throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range.");
+ return d_min_output_buffer[i];
+ }
+
+ /*!
+ * \brief Sets min buffer size on all output ports.
+ */
+ void set_min_output_buffer(long min_output_buffer) {
+ for(int i=0; i<output_signature()->max_streams(); i++) {
+ set_min_output_buffer(i, min_output_buffer);
+ }
+ }
+
+ /*!
+ * \brief Sets min buffer size on output port \p port.
+ */
+ void set_min_output_buffer(int port, long min_output_buffer) {
+ if((size_t)port >= d_min_output_buffer.size())
+ d_min_output_buffer.push_back(min_output_buffer);
+ else
+ d_min_output_buffer[port] = min_output_buffer;
+ }
+
// ----------------------------------------------------------------------------
private:
@@ -263,6 +370,8 @@ class GR_CORE_API gr_block : public gr_basic_block {
gr_block_detail_sptr d_detail; // implementation details
unsigned d_history;
bool d_fixed_rate;
+ bool d_max_noutput_items_set; // if d_max_noutput_items is valid
+ int d_max_noutput_items; // value of max_noutput_items for this block
tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
protected:
@@ -345,6 +454,10 @@ class GR_CORE_API gr_block : public gr_basic_block {
uint64_t abs_end,
const pmt::pmt_t &key);
+ std::vector<long> d_max_output_buffer;
+ std::vector<long> d_min_output_buffer;
+
+
// These are really only for internal use, but leaving them public avoids
// having to work up an ever-varying list of friend GR_CORE_APIs
diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i
index 4cc260bfe..db6c1d04a 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_block.i
@@ -52,6 +52,20 @@ class gr_block : public gr_basic_block {
uint64_t nitems_read(unsigned int which_input);
uint64_t nitems_written(unsigned int which_output);
+ // Methods to manage the block's max_noutput_items size.
+ int max_noutput_items();
+ void set_max_noutput_items(int m);
+ void unset_max_noutput_items();
+ bool is_set_max_noutput_items();
+
+ // Methods to manage block's min/max buffer sizes.
+ long max_output_buffer(int i);
+ void set_max_output_buffer(long max_output_buffer);
+ void set_max_output_buffer(int port, long max_output_buffer);
+ long min_output_buffer(int i);
+ void set_min_output_buffer(long min_output_buffer);
+ void set_min_output_buffer(int port, long min_output_buffer);
+
// internal use
gr_block_detail_sptr detail () const { return d_detail; }
void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
index 2792cd471..337c9518e 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
@@ -127,12 +127,6 @@ gr_block_detail::produce_each (int how_many_items)
}
-void
-gr_block_detail::_post(pmt_t msg)
-{
- d_tpb.insert_tail(msg);
-}
-
uint64_t
gr_block_detail::nitems_read(unsigned int which_input)
{
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h
index c96f00db8..16d9f4d42 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h
@@ -85,11 +85,6 @@ class GR_CORE_API gr_block_detail {
*/
void produce_each (int how_many_items);
- /*!
- * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
- */
- void _post(pmt::pmt_t msg);
-
// Return the number of items read on input stream which_input
uint64_t nitems_read(unsigned int which_input);
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index 6fea14613..375b58f56 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -206,7 +206,7 @@ gr_block_executor::run_one_iteration()
// determine the minimum available output space
noutput_items = min_available_space (d, m->output_multiple ());
- noutput_items = std::min(noutput_items, d_max_noutput_items);
+ noutput_items = std::min(noutput_items, max_noutput_items);
LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl);
if (noutput_items == -1) // we're done
goto were_done;
@@ -251,7 +251,7 @@ gr_block_executor::run_one_iteration()
// take a swag at how much output we can sink
noutput_items = (int) (max_items_avail * m->relative_rate ());
noutput_items = round_down (noutput_items, m->output_multiple ());
- noutput_items = std::min(noutput_items, d_max_noutput_items);
+ noutput_items = std::min(noutput_items, max_noutput_items);
LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl);
LOG(*d_log << " noutput_items = " << noutput_items << std::endl);
@@ -449,6 +449,7 @@ gr_block_executor::run_one_iteration()
// We didn't produce any output even though we called general_work.
// We have (most likely) consumed some input.
+ /*
// If this is a source, it's broken.
if (d->source_p()){
std::cerr << "gr_block_executor: source " << m
@@ -456,6 +457,7 @@ gr_block_executor::run_one_iteration()
// FIXME maybe we ought to raise an exception...
goto were_done;
}
+ */
// Have the caller try again...
return READY_NO_OUTPUT;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.cc b/gnuradio-core/src/lib/runtime/gr_block_registry.cc
new file mode 100644
index 000000000..ff23d97eb
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_block_registry.cc
@@ -0,0 +1,76 @@
+#include <gr_basic_block.h>
+#include <gr_block_registry.h>
+#include <gr_tpb_detail.h>
+#include <gr_block_detail.h>
+#include <gr_block.h>
+#include <stdio.h>
+
+gr_block_registry global_block_registry;
+
+gr_block_registry::gr_block_registry(){
+ d_ref_map = pmt::pmt_make_dict();
+}
+
+long gr_block_registry::block_register(gr_basic_block* block){
+ if(d_map.find(block->name()) == d_map.end()){
+ d_map[block->name()] = blocksubmap_t();
+ d_map[block->name()][0] = block;
+ return 0;
+ } else {
+ for(size_t i=0; i<=d_map[block->name()].size(); i++){
+ if(d_map[block->name()].find(i) == d_map[block->name()].end()){
+ d_map[block->name()][i] = block;
+ return i;
+ }
+ }
+ }
+ throw std::runtime_error("should not reach this");
+}
+
+void gr_block_registry::block_unregister(gr_basic_block* block){
+ d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id()));
+ d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->symbol_name()));
+ if(block->alias_set()){
+ d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->alias()));
+ }
+}
+
+std::string gr_block_registry::register_symbolic_name(gr_basic_block* block){
+ std::stringstream ss;
+ ss << block->name() << block->symbolic_id();
+ //std::cout << "register_symbolic_name: " << ss.str() << std::endl;
+ register_symbolic_name(block, ss.str());
+ return ss.str();
+}
+
+void gr_block_registry::register_symbolic_name(gr_basic_block* block, std::string name){
+ if(pmt_dict_has_key(d_ref_map, pmt::pmt_intern(name))){
+ throw std::runtime_error("symbol already exists, can not re-use!");
+ }
+ d_ref_map = pmt_dict_add(d_ref_map, pmt::pmt_intern(name), pmt::pmt_make_any(block));
+}
+
+gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){
+ pmt::pmt_t ref = pmt_dict_ref(d_ref_map, symbol, pmt::PMT_NIL);
+ if(pmt::pmt_eq(ref, pmt::PMT_NIL)){
+ throw std::runtime_error("block lookup failed! block not found!");
+ }
+ gr_basic_block* blk = boost::any_cast<gr_basic_block*>( pmt::pmt_any_ref(ref) );
+ return blk->shared_from_this();
+}
+
+
+void gr_block_registry::register_primitive(std::string blk, gr_block* ref){
+ primitive_map[blk] = ref;
+}
+
+void gr_block_registry::unregister_primitive(std::string blk){
+ primitive_map.erase(primitive_map.find(blk));
+}
+
+void gr_block_registry::notify_blk(std::string blk){
+ if(primitive_map.find(blk) == primitive_map.end()){ return; }
+ if(primitive_map[blk]->detail().get())
+ primitive_map[blk]->detail()->d_tpb.notify_msg();
+}
+
diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.h b/gnuradio-core/src/lib/runtime/gr_block_registry.h
new file mode 100644
index 000000000..6a2d939e5
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_block_registry.h
@@ -0,0 +1,42 @@
+#ifndef GR_BLOCK_REGISTRY_H
+#define GR_BLOCK_REGISTRY_H
+
+#include <map>
+
+#ifndef GR_BASIC_BLOCK_H
+class gr_basic_block;
+class gr_block;
+#endif
+
+class gr_block_registry {
+ public:
+ gr_block_registry();
+
+ long block_register(gr_basic_block* block);
+ void block_unregister(gr_basic_block* block);
+
+ std::string register_symbolic_name(gr_basic_block* block);
+ void register_symbolic_name(gr_basic_block* block, std::string name);
+
+ gr_basic_block_sptr block_lookup(pmt::pmt_t symbol);
+
+ void register_primitive(std::string blk, gr_block* ref);
+ void unregister_primitive(std::string blk);
+ void notify_blk(std::string blk);
+
+ private:
+
+ //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t;
+ typedef std::map< long, gr_basic_block* > blocksubmap_t;
+ typedef std::map< std::string, blocksubmap_t > blockmap_t;
+
+ blockmap_t d_map;
+ pmt::pmt_t d_ref_map;
+ std::map< std::string, gr_block*> primitive_map;
+
+};
+
+extern gr_block_registry global_block_registry;
+
+#endif
+
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
index 9005cd339..e04deb948 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
@@ -80,14 +80,23 @@ gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block)
int noutputs = calc_used_ports(block, false).size();
gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs);
+ gr_block_sptr grblock = cast_to_block_sptr(block);
+ if(!grblock)
+ throw std::runtime_error("allocate_block_detail found non-gr_block");
+
if (GR_FLAT_FLOWGRAPH_DEBUG)
std::cout << "Creating block detail for " << block << std::endl;
for (int i = 0; i < noutputs; i++) {
+ grblock->expand_minmax_buffer(i);
+
gr_buffer_sptr buffer = allocate_buffer(block, i);
if (GR_FLAT_FLOWGRAPH_DEBUG)
std::cout << "Allocated buffer for output " << block << ":" << i << std::endl;
detail->set_output(i, buffer);
+
+ // Update the block's max_output_buffer based on what was actually allocated.
+ grblock->set_max_output_buffer(i, buffer->bufsize());
}
return detail;
@@ -114,6 +123,21 @@ gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port)
// ensure we have a buffer at least twice their decimation factor*output_multiple
gr_basic_block_vector_t blocks = calc_downstream_blocks(block, port);
+ // limit buffer size if indicated
+ if(grblock->max_output_buffer(port) > 0) {
+// std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n";
+ nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port));
+ nitems -= nitems%grblock->output_multiple();
+ if( nitems < 1 )
+ throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!");
+ }
+ else if(grblock->min_output_buffer(port) > 0) {
+ nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port));
+ nitems -= nitems%grblock->output_multiple();
+ if( nitems < 1 )
+ throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!");
+ }
+
for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
gr_block_sptr dgrblock = cast_to_block_sptr(*p);
if (!dgrblock)
@@ -125,6 +149,7 @@ gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port)
nitems = std::max(nitems, static_cast<int>(2*(decimation*multiple+history)));
}
+// std::cout << "gr_make_buffer(" << nitems << ", " << item_size << ", " << grblock << "\n";
return gr_make_buffer(nitems, item_size, grblock);
}
diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
index 78e1bc99a..69c304a3d 100644
--- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
@@ -180,6 +180,11 @@ gr_flowgraph::calc_used_blocks()
{
gr_basic_block_vector_t tmp;
+ // make sure free standing message blocks are included
+ for (gr_basic_block_vector_t::iterator it=d_msgblocks.begin(); it!=d_msgblocks.end(); it++){
+ tmp.push_back(*it);
+ }
+
// Collect all blocks in the edge list
for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
tmp.push_back(p->src().block());
@@ -472,3 +477,7 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve
output.push_back(block);
}
+void gr_flowgraph::add_msg_block(gr_basic_block_sptr blk){
+ d_msgblocks.push_back(blk);
+}
+
diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flowgraph.h
index a2c1580eb..860cb0ff1 100644
--- a/gnuradio-core/src/lib/runtime/gr_flowgraph.h
+++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.h
@@ -110,6 +110,8 @@ public:
void disconnect(gr_basic_block_sptr src_block, int src_port,
gr_basic_block_sptr dst_block, int dst_port);
+ void add_msg_block(gr_basic_block_sptr blk);
+
// Validate connectivity, raise exception if invalid
void validate();
@@ -128,6 +130,7 @@ public:
// Return vector of vectors of disjointly connected blocks, topologically
// sorted.
std::vector<gr_basic_block_vector_t> partition();
+ gr_basic_block_vector_t d_msgblocks;
protected:
gr_basic_block_vector_t d_blocks;
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
index 756852df8..a19bfe195 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
@@ -81,6 +81,36 @@ gr_hier_block2::connect(gr_basic_block_sptr src, int src_port,
}
void
+gr_hier_block2::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); }
+ d_detail->msg_connect(src, srcport, dst, dstport);
+}
+
+void
+gr_hier_block2::msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+{
+ d_detail->msg_connect(src, pmt::mp(srcport), dst, pmt::mp(dstport));
+}
+
+void
+gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); }
+ d_detail->msg_disconnect(src, srcport, dst, dstport);
+}
+
+void
+gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+{
+ d_detail->msg_disconnect(src, pmt::mp(srcport), dst, pmt::mp(dstport));
+}
+
+void
gr_hier_block2::disconnect(gr_basic_block_sptr block)
{
d_detail->disconnect(block);
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h
index 123178724..e8364a740 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h
@@ -98,6 +98,21 @@ public:
gr_basic_block_sptr dst, int dst_port);
/*!
+ * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together
+ *
+ * This adds (if not done earlier by another connect) a pair of gr-blocks or
+ * hierarchical blocks to the internal message port subscription
+ */
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport);
+
+ /*!
* \brief Remove a gr-block or hierarchical block from the internal flowgraph.
*
* This removes a gr-block or hierarchical block from the internal flowgraph,
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i
index eefb965b4..7c0e62f28 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.i
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i
@@ -38,6 +38,8 @@ gr_hier_block2_sptr gr_make_hier_block2(const std::string name,
// better interface in scripting land.
%rename(primitive_connect) gr_hier_block2::connect;
%rename(primitive_disconnect) gr_hier_block2::disconnect;
+%rename(primitive_msg_connect) gr_hier_block2::msg_connect;
+%rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect;
class gr_hier_block2 : public gr_basic_block
{
@@ -54,6 +56,19 @@ public:
void connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port)
throw (std::invalid_argument);
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+ throw (std::runtime_error);
+ void msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+ throw (std::runtime_error);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+ throw (std::runtime_error);
+ void msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+ throw (std::runtime_error);
+
void disconnect(gr_basic_block_sptr block)
throw (std::invalid_argument);
void disconnect(gr_basic_block_sptr src, int src_port,
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
index 76c5ce06f..ff2a5db8c 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
@@ -144,6 +144,36 @@ gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port,
}
void
+gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "connecting message port..." << std::endl;
+
+ // register the subscription
+ src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport));
+
+ // add block uniquely to list to internal blocks
+ if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){
+ d_blocks.push_back(dst);
+ }
+
+ // make sure we instantiate a thread for this block
+ d_fg->add_msg_block(dst);
+}
+
+void
+gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "disconnecting message port..." << std::endl;
+
+ // register the subscription
+ src->message_port_unsub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport));
+}
+
+void
gr_hier_block2_detail::disconnect(gr_basic_block_sptr block)
{
// Check on singleton list
@@ -427,6 +457,7 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const
}
}
}
+ sfg->d_msgblocks = d_fg->d_msgblocks;
// Construct unique list of blocks used either in edges, inputs,
// outputs, or by themselves. I still hate STL.
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
index f4f950e9d..f2d2b3c4e 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
@@ -39,6 +39,10 @@ public:
void connect(gr_basic_block_sptr block);
void connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port);
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
void disconnect(gr_basic_block_sptr block);
void disconnect(gr_basic_block_sptr, int src_port,
gr_basic_block_sptr, int dst_port);
diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc
index 5018ee9e6..93d5fb20e 100644
--- a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc
+++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc
@@ -41,12 +41,12 @@ gr_msg_accepter::~gr_msg_accepter()
}
void
-gr_msg_accepter::post(pmt_t msg)
+gr_msg_accepter::post(pmt_t which_port, pmt_t msg)
{
// Notify derived class, handled case by case
gr_block *p = dynamic_cast<gr_block *>(this);
if (p) {
- p->detail()->_post(msg);
+ p->_post(which_port,msg);
return;
}
gr_hier_block2 *p2 = dynamic_cast<gr_hier_block2 *>(this);
diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h
index 3e5c97638..a497ba6e7 100644
--- a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h
+++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h
@@ -36,7 +36,7 @@ public:
gr_msg_accepter();
~gr_msg_accepter();
- void post(pmt::pmt_t msg);
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg);
};
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc
index 131ddd19c..2824eb1b3 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc
@@ -74,6 +74,11 @@ gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_i
for (size_t i = 0; i < blocks.size(); i++){
std::stringstream name;
name << "thread-per-block[" << i << "]: " << blocks[i];
+
+ // If set, use internal value instead of global value
+ if(blocks[i]->is_set_max_noutput_items())
+ max_noutput_items = blocks[i]->max_noutput_items();
+
d_threads.create_thread(
gruel::thread_body_wrapper<tpb_container>(tpb_container(blocks[i], max_noutput_items),
name.str()));
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc
index 46b33d91f..46eb6bbe0 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc
@@ -68,43 +68,3 @@ gr_tpb_detail::notify_neighbors(gr_block_detail *d)
notify_upstream(d);
}
-void
-gr_tpb_detail::insert_tail(pmt::pmt_t msg)
-{
- gruel::scoped_lock guard(mutex);
-
- msg_queue.push_back(msg);
-
- // wake up thread if BLKD_IN or BLKD_OUT
- input_cond.notify_one();
- output_cond.notify_one();
-}
-
-pmt_t
-gr_tpb_detail::delete_head_nowait()
-{
- gruel::scoped_lock guard(mutex);
-
- if (empty_p())
- return pmt_t();
-
- pmt_t m(msg_queue.front());
- msg_queue.pop_front();
-
- return m;
-}
-
-/*
- * Caller must already be holding the mutex
- */
-pmt_t
-gr_tpb_detail::delete_head_nowait_already_holding_mutex()
-{
- if (empty_p())
- return pmt_t();
-
- pmt_t m(msg_queue.front());
- msg_queue.pop_front();
-
- return m;
-}
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h
index b6e342dee..69feb6007 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h
@@ -39,9 +39,6 @@ struct GR_CORE_API gr_tpb_detail {
bool output_changed;
gruel::condition_variable output_cond;
-private:
- std::deque<pmt::pmt_t> msg_queue;
-
public:
gr_tpb_detail()
: input_changed(false), output_changed(false) { }
@@ -55,6 +52,12 @@ public:
//! Called by us to notify both upstream and downstream
void notify_neighbors(gr_block_detail *d);
+ //! Called by pmt msg posters
+ void notify_msg(){
+ input_cond.notify_one();
+ output_cond.notify_one();
+ }
+
//! Called by us
void clear_changed()
{
@@ -63,23 +66,6 @@ public:
output_changed = false;
}
- //! is the queue empty?
- bool empty_p() const { return msg_queue.empty(); }
-
- //| Acquires and release the mutex
- void insert_tail(pmt::pmt_t msg);
-
- /*!
- * \returns returns pmt at head of queue or pmt_t() if empty.
- */
- pmt::pmt_t delete_head_nowait();
-
- /*!
- * \returns returns pmt at head of queue or pmt_t() if empty.
- * Caller must already be holding the mutex
- */
- pmt::pmt_t delete_head_nowait_already_holding_mutex();
-
private:
//! Used by notify_downstream
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
index a5aabb379..9f17a48a8 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
@@ -25,13 +25,14 @@
#include <iostream>
#include <boost/thread.hpp>
#include <gruel/pmt.h>
+#include <boost/foreach.hpp>
using namespace pmt;
gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items)
: d_exec(block, max_noutput_items)
{
- // std::cerr << "gr_tpb_thread_body: " << block << std::endl;
+ //std::cerr << "gr_tpb_thread_body: " << block << std::endl;
gr_block_detail *d = block->detail().get();
gr_block_executor::state s;
@@ -42,11 +43,22 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
boost::this_thread::interruption_point();
// handle any queued up messages
- while ((msg = d->d_tpb.delete_head_nowait()))
- block->dispatch_msg(msg);
+ //BOOST_FOREACH( pmt::pmt_t port, block->msg_queue.keys() )
+
+ BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue )
+ {
+ while ((msg = block->delete_head_nowait(i.first))){
+ block->dispatch_msg(i.first,msg);
+ }
+ }
d->d_tpb.clear_changed();
- s = d_exec.run_one_iteration();
+ // run one iteration if we are a connected stream block
+ if(d->noutputs() >0 || d->ninputs()>0){
+ s = d_exec.run_one_iteration();
+ } else {
+ s = gr_block_executor::BLKD_IN;
+ }
switch(s){
case gr_block_executor::READY: // Tell neighbors we made progress.
@@ -67,15 +79,18 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
while (!d->d_tpb.input_changed){
// wait for input or message
- while(!d->d_tpb.input_changed && d->d_tpb.empty_p())
+ while(!d->d_tpb.input_changed && block->empty_p())
d->d_tpb.input_cond.wait(guard);
// handle all pending messages
- while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){
- guard.unlock(); // release lock while processing msg
- block->dispatch_msg(msg);
- guard.lock();
- }
+ BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue )
+ {
+ while ((msg = block->delete_head_nowait(i.first))){
+ guard.unlock(); // release lock while processing msg
+ block->dispatch_msg(i.first, msg);
+ guard.lock();
+ }
+ }
}
}
break;
@@ -87,15 +102,18 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
while (!d->d_tpb.output_changed){
// wait for output room or message
- while(!d->d_tpb.output_changed && d->d_tpb.empty_p())
+ while(!d->d_tpb.output_changed && block->empty_p())
d->d_tpb.output_cond.wait(guard);
// handle all pending messages
- while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){
- guard.unlock(); // release lock while processing msg
- block->dispatch_msg(msg);
- guard.lock();
- }
+ BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue )
+ {
+ while ((msg = block->delete_head_nowait(i.first))){
+ guard.unlock(); // release lock while processing msg
+ block->dispatch_msg(i.first,msg);
+ guard.lock();
+ }
+ }
}
}
break;
diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
index cc7b7c720..a0b4755a8 100644
--- a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
+++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
@@ -27,6 +27,7 @@
#include <qa_gr_top_block.h>
#include <gr_top_block.h>
#include <gr_head.h>
+#include <gr_nop.h>
#include <gr_null_source.h>
#include <gr_null_sink.h>
#include <iostream>
@@ -119,3 +120,145 @@ void qa_gr_top_block::t4_reconfigure()
// Wait for flowgraph to end on its own
tb->wait();
}
+
+
+void qa_gr_top_block::t5_max_noutputs()
+{
+ if (VERBOSE) std::cout << "qa_gr_top_block::t5()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_block_sptr head = gr_make_head(sizeof(int), 100000);
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ // Start infinite flowgraph
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, dst, 0);
+ tb->start(100);
+ tb->wait();
+}
+
+void qa_gr_top_block::t6_reconfig_max_noutputs()
+{
+ if (VERBOSE) std::cout << "qa_gr_top_block::t6()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_block_sptr head = gr_make_head(sizeof(int), 100000);
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ // Start infinite flowgraph
+ tb->connect(src, 0, dst, 0);
+ tb->start(100);
+
+ // Reconfigure with gr_head in the middle
+ tb->lock();
+ tb->disconnect(src, 0, dst, 0);
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, dst, 0);
+ tb->set_max_noutput_items(1000);
+ head->set_max_noutput_items(500);
+ tb->unlock();
+
+ // Wait for flowgraph to end on its own
+ tb->wait();
+}
+
+void qa_gr_top_block::t7_max_noutputs_per_block()
+{
+ if (VERBOSE) std::cout << "qa_gr_top_block::t7()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_block_sptr head = gr_make_head(sizeof(int), 100000);
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ head->set_max_noutput_items(100);
+
+ // Start infinite flowgraph
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, dst, 0);
+ tb->start();
+ tb->wait();
+}
+
+void qa_gr_top_block::t8_reconfig_max_noutputs_per_block()
+{
+ if (VERBOSE) std::cout << "qa_gr_top_block::t8()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_block_sptr head = gr_make_head(sizeof(int), 100000);
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ head->set_max_noutput_items(99);
+
+ // Start infinite flowgraph
+ tb->connect(src, 0, dst, 0);
+ tb->start(201);
+
+ // Reconfigure with gr_head in the middle
+ tb->lock();
+ tb->disconnect(src, 0, dst, 0);
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, dst, 0);
+ tb->set_max_noutput_items(1023);
+ head->set_max_noutput_items(513);
+ tb->unlock();
+
+ // Wait for flowgraph to end on its own
+ tb->wait();
+}
+
+void qa_gr_top_block::t9_max_output_buffer()
+{
+ if (VERBOSE) std::cout << "qa_gr_top_block::t9()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_block_sptr head = gr_make_head(sizeof(int), 100000);
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ head->set_max_output_buffer(1024);
+
+ // Start infinite flowgraph
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, dst, 0);
+ tb->start();
+ tb->wait();
+}
+
+void qa_gr_top_block::t10_reconfig_max_output_buffer()
+{
+ if (VERBOSE) std::cout << "qa_gr_top_block::t10()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_block_sptr head = gr_make_head(sizeof(int), 100000);
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ head->set_max_output_buffer(1000);
+
+ // Start infinite flowgraph
+ tb->connect(src, 0, dst, 0);
+ tb->start(201);
+
+ // Reconfigure with gr_head in the middle
+ tb->lock();
+ gr_block_sptr nop = gr_make_nop(sizeof(int));
+ nop->set_max_output_buffer(4000);
+ tb->disconnect(src, 0, dst, 0);
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, nop, 0);
+ tb->connect(nop, 0, dst, 0);
+ tb->unlock();
+
+ // Wait for flowgraph to end on its own
+ tb->wait();
+}
diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
index b223633e5..bb891abca 100644
--- a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
+++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
@@ -36,6 +36,8 @@ class qa_gr_top_block : public CppUnit::TestCase
CPPUNIT_TEST(t2_start_stop_wait);
CPPUNIT_TEST(t3_lock_unlock);
CPPUNIT_TEST(t4_reconfigure); // triggers 'join never returns' bug
+ CPPUNIT_TEST(t5_max_noutputs);
+ CPPUNIT_TEST(t6_reconfig_max_noutputs);
CPPUNIT_TEST_SUITE_END();
@@ -46,6 +48,12 @@ private:
void t2_start_stop_wait();
void t3_lock_unlock();
void t4_reconfigure();
+ void t5_max_noutputs();
+ void t6_reconfig_max_noutputs();
+ void t7_max_noutputs_per_block();
+ void t8_reconfig_max_noutputs_per_block();
+ void t9_max_output_buffer();
+ void t10_reconfig_max_output_buffer();
};
#endif /* INCLUDED_QA_GR_TOP_BLOCK_H */
diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
index 25ae0b1e1..c84a219bd 100644
--- a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
+++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
@@ -65,15 +65,11 @@ void qa_set_msg_handler::t0()
tb->start();
// Send them...
+ pmt_t port(pmt_intern("port"));
for (int i = 0; i < NMSGS; i++){
- send(nop, mp(mp("example-msg"), mp(i)));
+ send(nop, port, mp(mp("example-msg"), mp(i)));
}
- // And send a message to null_source to confirm that the default
- // message handling action (which should be a nop) doesn't dump
- // core.
- send(src, mp(mp("example-msg"), mp(0)));
-
// Give the messages a chance to be processed
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py
index 77bf0607a..cf58a9763 100644
--- a/gnuradio-core/src/python/build_utils.py
+++ b/gnuradio-core/src/python/build_utils.py
@@ -1,5 +1,5 @@
#
-# Copyright 2004,2009 Free Software Foundation, Inc.
+# Copyright 2004,2009,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -179,7 +179,9 @@ def is_complex (code3):
def standard_dict (name, code3, package='gr'):
d = {}
d['NAME'] = name
- d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper ()
+ 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'
@@ -210,7 +212,7 @@ def standard_impl_dict2 (name, code3, package):
d = {}
d['NAME'] = name
d['IMPL_NAME'] = name
- d['BASE_NAME'] = name.rstrip("_impl")
+ 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
diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
index 6a0555021..62f3d7e46 100644
--- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
+++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
@@ -23,6 +23,7 @@ include(GrPython)
GR_PYTHON_INSTALL(FILES
__init__.py
exceptions.py
+ gateway.py
gr_threading.py
gr_threading_23.py
gr_threading_24.py
@@ -42,6 +43,13 @@ 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_PYTHON_DIRS
+ ${CMAKE_SOURCE_DIR}/gruel/src/python
+ ${CMAKE_BINARY_DIR}/gruel/src/swig
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/python
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
+ )
+ set(GR_TEST_TARGET_DEPS volk gruel gnuradio-core)
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
index 602d1119f..5d01ea11b 100644
--- a/gnuradio-core/src/python/gnuradio/gr/__init__.py
+++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py
@@ -1,5 +1,5 @@
#
-# Copyright 2003,2004,2006,2008,2009,2010 Free Software Foundation, Inc.
+# Copyright 2003-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -24,29 +24,11 @@
# This is the main GNU Radio python module.
# We pull the swig output and the other modules into the gnuradio.gr namespace
-# Temporary workaround for ticket:181.
-# Use leading underscores to avoid namespace pollution
-import sys
-_RTLD_GLOBAL = 0
-try:
- from dl import RTLD_GLOBAL as _RTLD_GLOBAL
-except ImportError:
- try:
- from DLFCN import RTLD_GLOBAL as _RTLD_GLOBAL
- except ImportError:
- pass
-
-if _RTLD_GLOBAL != 0:
- _dlopenflags = sys.getdlopenflags()
- sys.setdlopenflags(_dlopenflags|_RTLD_GLOBAL)
-
from gnuradio_core import *
from exceptions import *
from hier_block2 import *
from top_block import *
-
-if _RTLD_GLOBAL != 0:
- sys.setdlopenflags(_dlopenflags) # Restore original flags
+from gateway import basic_block, sync_block, decim_block, interp_block
# create a couple of aliases
serial_to_parallel = stream_to_vector
diff --git a/gnuradio-core/src/python/gnuradio/gr/gateway.py b/gnuradio-core/src/python/gnuradio/gr/gateway.py
new file mode 100644
index 000000000..244b8b592
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/gateway.py
@@ -0,0 +1,215 @@
+#
+# 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
+
+########################################################################
+# 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()
+
+ #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
+
+########################################################################
+# 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/qa_block_gateway.py b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py
new file mode 100644
index 000000000..911879f6f
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py
@@ -0,0 +1,235 @@
+#
+# 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.
+#
+
+from gnuradio import gr, gr_unittest
+import pmt
+import numpy
+
+class add_2_f32_1_f32(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "add 2 f32",
+ in_sig = [numpy.float32, numpy.float32],
+ out_sig = [numpy.float32],
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = input_items[0] + input_items[1]
+ return len(output_items[0])
+
+class add_2_fc32_1_fc32(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "add 2 fc32",
+ in_sig = [numpy.complex64, numpy.complex64],
+ out_sig = [numpy.complex64],
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = input_items[0] + input_items[1]
+ return len(output_items[0])
+
+class convolve(gr.sync_block):
+ """
+ A demonstration using block history to properly perform a convolution.
+ """
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "convolve",
+ in_sig = [numpy.float32],
+ out_sig = [numpy.float32]
+ )
+ self._taps = [1, 0, 0, 0]
+ self.set_history(len(self._taps))
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = numpy.convolve(input_items[0], self._taps, mode='valid')
+ return len(output_items[0])
+
+class decim2x(gr.decim_block):
+ def __init__(self):
+ gr.decim_block.__init__(
+ self,
+ name = "decim2x",
+ in_sig = [numpy.float32],
+ out_sig = [numpy.float32],
+ decim = 2
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = input_items[0][::2]
+ return len(output_items[0])
+
+class interp2x(gr.interp_block):
+ def __init__(self):
+ gr.interp_block.__init__(
+ self,
+ name = "interp2x",
+ in_sig = [numpy.float32],
+ out_sig = [numpy.float32],
+ interp = 2
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][1::2] = input_items[0]
+ output_items[0][::2] = input_items[0]
+ return len(output_items[0])
+
+class tag_source(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "tag source",
+ in_sig = None,
+ out_sig = [numpy.float32],
+ )
+
+ def work(self, input_items, output_items):
+ num_output_items = len(output_items[0])
+
+ #put code here to fill the output items...
+
+ #make a new tag on the middle element every time work is called
+ count = self.nitems_written(0) + num_output_items/2
+ key = pmt.pmt_string_to_symbol("example_key")
+ value = pmt.pmt_string_to_symbol("example_value")
+ self.add_item_tag(0, count, key, value)
+
+ return num_output_items
+
+class tag_sink(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "tag sink",
+ in_sig = [numpy.float32],
+ out_sig = None,
+ )
+ self.key = None
+
+ def work(self, input_items, output_items):
+ num_input_items = len(input_items[0])
+
+ #put code here to process the input items...
+
+ #print all the tags received in this work call
+ nread = self.nitems_read(0)
+ tags = self.get_tags_in_range(0, nread, nread+num_input_items)
+ for tag in tags:
+ #print tag.offset
+ #print pmt.pmt_symbol_to_string(tag.key)
+ #print pmt.pmt_symbol_to_string(tag.value)
+ self.key = pmt.pmt_symbol_to_string(tag.key)
+
+ return num_input_items
+
+class fc32_to_f32_2(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "fc32_to_f32_2",
+ in_sig = [numpy.complex64],
+ out_sig = [(numpy.float32, 2)],
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][::,0] = numpy.real(input_items[0])
+ output_items[0][::,1] = numpy.imag(input_items[0])
+ return len(output_items[0])
+
+class test_block_gateway(gr_unittest.TestCase):
+
+ def test_add_f32(self):
+ tb = gr.top_block()
+ src0 = gr.vector_source_f([1, 3, 5, 7, 9], False)
+ src1 = gr.vector_source_f([0, 2, 4, 6, 8], False)
+ adder = add_2_f32_1_f32()
+ sink = gr.vector_sink_f()
+ tb.connect((src0, 0), (adder, 0))
+ tb.connect((src1, 0), (adder, 1))
+ tb.connect(adder, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 5, 9, 13, 17))
+
+ def test_add_fc32(self):
+ tb = gr.top_block()
+ src0 = gr.vector_source_c([1, 3j, 5, 7j, 9], False)
+ src1 = gr.vector_source_c([0, 2j, 4, 6j, 8], False)
+ adder = add_2_fc32_1_fc32()
+ sink = gr.vector_sink_c()
+ tb.connect((src0, 0), (adder, 0))
+ tb.connect((src1, 0), (adder, 1))
+ tb.connect(adder, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 5j, 9, 13j, 17))
+
+ def test_convolve(self):
+ tb = gr.top_block()
+ src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False)
+ cv = convolve()
+ sink = gr.vector_sink_f()
+ tb.connect(src, cv, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8))
+
+ def test_decim2x(self):
+ tb = gr.top_block()
+ src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False)
+ d2x = decim2x()
+ sink = gr.vector_sink_f()
+ tb.connect(src, d2x, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 3, 5, 7))
+
+ def test_interp2x(self):
+ tb = gr.top_block()
+ src = gr.vector_source_f([1, 3, 5, 7, 9], False)
+ i2x = interp2x()
+ sink = gr.vector_sink_f()
+ tb.connect(src, i2x, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 1, 3, 3, 5, 5, 7, 7, 9, 9))
+
+ def test_tags(self):
+ src = tag_source()
+ sink = tag_sink()
+ head = gr.head(gr.sizeof_float, 50000) #should be enough items to get a tag through
+ tb = gr.top_block()
+ tb.connect(src, head, sink)
+ tb.run()
+ self.assertEqual(sink.key, "example_key")
+
+ def test_fc32_to_f32_2(self):
+ tb = gr.top_block()
+ src = gr.vector_source_c([1+2j, 3+4j, 5+6j, 7+8j, 9+10j], False)
+ convert = fc32_to_f32_2()
+ v2s = gr.vector_to_stream(gr.sizeof_float, 2)
+ sink = gr.vector_sink_f()
+ tb.connect(src, convert, v2s, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+if __name__ == '__main__':
+ gr_unittest.run(test_block_gateway, "test_block_gateway.xml")
+
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
new file mode 100755
index 000000000..64eb80a8f
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
@@ -0,0 +1,70 @@
+#!/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.
+#
+
+from gnuradio import gr, gr_unittest
+from gruel import pmt
+import time;
+class test_pdu(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ # Just run some data through and make sure it doesn't puke.
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+
+ src = gr.pdu_to_tagged_stream(gr.BYTE);
+ snk3 = gr.tagged_stream_to_pdu(gr.BYTE);
+ snk2 = gr.vector_sink_b();
+ snk = gr.tag_debug(1, "test");
+
+ dbg = gr.message_debug();
+
+ self.tb.connect(src, snk)
+ self.tb.connect(src, snk2)
+ self.tb.connect(src, snk3)
+
+ self.tb.msg_connect(snk3, "pdus", dbg, "print");
+ self.tb.start()
+
+ # make our reference and message pmts
+ port = pmt.pmt_intern("pdus");
+ msg = pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(16, 0xFF) );
+
+ print "printing port & msg"
+ pmt.pmt_print(port);
+ pmt.pmt_print(msg);
+
+ # post the message
+ src.to_basic_block()._post( port, msg );
+
+ time.sleep(1);
+ self.tb.stop();
+ self.tb.wait();
+
+ print snk2.data();
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pdu, "test_pdu.xml")
diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py
index 43af8073b..dc1f443aa 100644
--- a/gnuradio-core/src/python/gnuradio/gr/top_block.py
+++ b/gnuradio-core/src/python/gnuradio/gr/top_block.py
@@ -123,6 +123,12 @@ class top_block(object):
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)