summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2017-04-26 20:15:20 +0000
committerRuben Undheim <ruben.undheim@gmail.com>2017-05-19 18:03:27 +0000
commit7a6dace271a53faccec6d691477e2c5ccc5e9d49 (patch)
treeffab940bd1e7debaa7c321e8ce16a38fa6efd29c
parent0e32fcaf928e8f3f9161a619201d3cf253a46ded (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.xml19
-rw-r--r--gr-blocks/include/gnuradio/blocks/file_source.h5
-rw-r--r--gr-blocks/lib/file_source_impl.cc25
-rw-r--r--gr-blocks/lib/file_source_impl.h9
-rw-r--r--gr-blocks/python/blocks/qa_file_source_sink.py63
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 &gt; 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")