diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2017-04-26 20:15:20 +0000 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2017-05-19 18:03:27 +0000 |
commit | 7a6dace271a53faccec6d691477e2c5ccc5e9d49 (patch) | |
tree | ffab940bd1e7debaa7c321e8ce16a38fa6efd29c | |
parent | 0e32fcaf928e8f3f9161a619201d3cf253a46ded (diff) |
blocks: file_source ("file_begin" stream tag)
- Add a configurable "file_begin" stream tag
which is especially useful in repeat mode.
- Added unit tests for new functionality
-rw-r--r-- | gr-blocks/grc/blocks_file_source.xml | 19 | ||||
-rw-r--r-- | gr-blocks/include/gnuradio/blocks/file_source.h | 5 | ||||
-rw-r--r-- | gr-blocks/lib/file_source_impl.cc | 25 | ||||
-rw-r--r-- | gr-blocks/lib/file_source_impl.h | 9 | ||||
-rw-r--r-- | gr-blocks/python/blocks/qa_file_source_sink.py | 63 |
5 files changed, 119 insertions, 2 deletions
diff --git a/gr-blocks/grc/blocks_file_source.xml b/gr-blocks/grc/blocks_file_source.xml index 7ac573f2da..22c5263171 100644 --- a/gr-blocks/grc/blocks_file_source.xml +++ b/gr-blocks/grc/blocks_file_source.xml @@ -8,8 +8,10 @@ <name>File Source</name> <key>blocks_file_source</key> <import>from gnuradio import blocks</import> - <make>blocks.file_source($type.size*$vlen, $file, $repeat)</make> + <make>blocks.file_source($type.size*$vlen, $file, $repeat) +self.$(id).set_begin_tag($begin_tag)</make> <callback>open($file, $repeat)</callback> + <callback>self.$(id).set_begin_tag($begin_tag)</callback> <param> <name>File</name> <key>file</key> @@ -66,6 +68,21 @@ <value>1</value> <type>int</type> </param> + + <param> + <name>Add begin tag</name> + <key>begin_tag</key> + <value>False</value> + <type>bool</type> + <option> + <name>Yes</name> + <key>True</key> + </option> + <option> + <name>No</name> + <key>False</key> + </option> + </param> <check>$vlen > 0</check> <source> <name>out</name> diff --git a/gr-blocks/include/gnuradio/blocks/file_source.h b/gr-blocks/include/gnuradio/blocks/file_source.h index 5682853a35..bba09ad502 100644 --- a/gr-blocks/include/gnuradio/blocks/file_source.h +++ b/gr-blocks/include/gnuradio/blocks/file_source.h @@ -77,6 +77,11 @@ namespace gr { * \brief Close the file handle. */ virtual void close() = 0; + + /*! + * \brief Add a stream tag to the first sample of the file if true + */ + virtual void set_begin_tag(bool val) = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/lib/file_source_impl.cc b/gr-blocks/lib/file_source_impl.cc index 1602b02416..2f626d0897 100644 --- a/gr-blocks/lib/file_source_impl.cc +++ b/gr-blocks/lib/file_source_impl.cc @@ -64,10 +64,15 @@ namespace gr { io_signature::make(0, 0, 0), io_signature::make(1, 1, itemsize)), d_itemsize(itemsize), d_fp(0), d_new_fp(0), d_repeat(repeat), - d_updated(false) + d_updated(false), d_file_begin(true), d_repeat_cnt(0), + d_add_begin_tag(false) { open(filename, repeat); do_update(); + + std::stringstream str; + str << name() << unique_id(); + _id = pmt::string_to_symbol(str.str()); } file_source_impl::~file_source_impl() @@ -139,9 +144,16 @@ namespace gr { d_fp = d_new_fp; // install new file pointer d_new_fp = 0; d_updated = false; + d_file_begin = true; } } + void + file_source_impl::set_begin_tag(bool val) + { + d_add_begin_tag = val; + } + int file_source_impl::work(int noutput_items, gr_vector_const_void_star &input_items, @@ -156,7 +168,14 @@ namespace gr { throw std::runtime_error("work with file not open"); gr::thread::scoped_lock lock(fp_mutex); // hold for the rest of this function + while(size) { + // Add stream tag whenever the file starts again + if (d_file_begin && d_add_begin_tag) { + add_item_tag(0, nitems_written(0) + noutput_items - size, BEGIN_KEY, pmt::from_long(d_repeat_cnt), _id); + d_file_begin = false; + } + i = fread(o, d_itemsize, size, (FILE*)d_fp); size -= i; @@ -178,6 +197,10 @@ namespace gr { fprintf(stderr, "[%s] fseek failed\n", __FILE__); exit(-1); } + if (d_add_begin_tag) { + d_file_begin = true; + d_repeat_cnt++; + } } if(size > 0) { // EOF or error diff --git a/gr-blocks/lib/file_source_impl.h b/gr-blocks/lib/file_source_impl.h index 80232a1dbe..3cde2bb11a 100644 --- a/gr-blocks/lib/file_source_impl.h +++ b/gr-blocks/lib/file_source_impl.h @@ -26,6 +26,8 @@ #include <gnuradio/blocks/file_source.h> #include <boost/thread/mutex.hpp> +static const pmt::pmt_t BEGIN_KEY = pmt::string_to_symbol("file_begin"); + namespace gr { namespace blocks { @@ -37,7 +39,12 @@ namespace gr { FILE *d_new_fp; bool d_repeat; bool d_updated; + bool d_file_begin; + long d_repeat_cnt; + bool d_add_begin_tag; + boost::mutex fp_mutex; + pmt::pmt_t _id; void do_update(); @@ -52,6 +59,8 @@ namespace gr { int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + void set_begin_tag(bool val); }; } /* namespace blocks */ diff --git a/gr-blocks/python/blocks/qa_file_source_sink.py b/gr-blocks/python/blocks/qa_file_source_sink.py index da1a07b347..0a5887d442 100644 --- a/gr-blocks/python/blocks/qa_file_source_sink.py +++ b/gr-blocks/python/blocks/qa_file_source_sink.py @@ -55,6 +55,7 @@ class test_file_source_sink(gr_unittest.TestCase): result_data = snk2.data() self.assertFloatTuplesAlmostEqual(expected_result, result_data) + self.assertEqual(len(snk2.tags()), 0) def test_descriptor_001(self): src_data = range(1000) @@ -86,6 +87,7 @@ class test_file_source_sink(gr_unittest.TestCase): result_data = snk2.data() self.assertFloatTuplesAlmostEqual(expected_result, result_data) + self.assertEqual(len(snk2.tags()), 0) def test_file_source_can_seek_after_open(self): src_data = range(1000) @@ -101,6 +103,67 @@ class test_file_source_sink(gr_unittest.TestCase): source = blocks.file_source(gr.sizeof_float, temp.name) self.assertTrue(source.seek(0, os.SEEK_SET)) + def test_begin_tag(self): + src_data = range(1000) + expected_result = range(1000) + + filename = "tmp.32f" + src = blocks.vector_source_f(src_data) + snk = blocks.file_sink(gr.sizeof_float, filename) + snk.set_unbuffered(True) + + src2 = blocks.file_source(gr.sizeof_float, filename) + src2.set_begin_tag(True) + snk2 = blocks.vector_sink_f() + + self.tb.connect(src, snk) + self.tb.run() + + self.tb.disconnect(src, snk) + self.tb.connect(src2, snk2) + self.tb.run() + + os.remove(filename) + + result_data = snk2.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + self.assertEqual(len(snk2.tags()), 1) + + def test_begin_tag_repeat(self): + src_data = range(1000) + expected_result = range(1000) + expected_result.extend(range(1000)) + + filename = "tmp.32f" + src = blocks.vector_source_f(src_data) + snk = blocks.file_sink(gr.sizeof_float, filename) + snk.set_unbuffered(True) + + src2 = blocks.file_source(gr.sizeof_float, filename, True) + src2.set_begin_tag(True) + hd = blocks.head(gr.sizeof_float, 2000) + snk2 = blocks.vector_sink_f() + + self.tb.connect(src, snk) + self.tb.run() + + self.tb.disconnect(src, snk) + self.tb.connect(src2, hd, snk2) + self.tb.run() + + os.remove(filename) + + result_data = snk2.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + tags = snk2.tags() + self.assertEqual(len(tags), 2) + self.assertEqual(str(tags[0].key), "file_begin") + self.assertEqual(str(tags[0].value), "0") + self.assertEqual(tags[0].offset, 0) + self.assertEqual(str(tags[1].key), "file_begin") + self.assertEqual(str(tags[1].value), "1") + self.assertEqual(tags[1].offset, 1000) + if __name__ == '__main__': gr_unittest.run(test_file_source_sink, "test_file_source_sink.xml") |