1 /* -*- c++ -*- */
2 /*
3  * Copyright 2010,2013 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include "annotator_raw_impl.h"
28 #include <gnuradio/io_signature.h>
29 #include <string.h>
30 #include <iomanip>
31 #include <iostream>
32 #include <stdexcept>
33 
34 using namespace pmt;
35 
36 namespace gr {
37 namespace blocks {
38 
make(size_t sizeof_stream_item)39 annotator_raw::sptr annotator_raw::make(size_t sizeof_stream_item)
40 {
41     return gnuradio::get_initial_sptr(new annotator_raw_impl(sizeof_stream_item));
42 }
43 
annotator_raw_impl(size_t sizeof_stream_item)44 annotator_raw_impl::annotator_raw_impl(size_t sizeof_stream_item)
45     : sync_block("annotator_raw",
46                  io_signature::make(1, 1, sizeof_stream_item),
47                  io_signature::make(1, 1, sizeof_stream_item)),
48       d_itemsize(sizeof_stream_item)
49 {
50     set_tag_propagation_policy(TPP_ONE_TO_ONE);
51     set_relative_rate(1, 1);
52 }
53 
~annotator_raw_impl()54 annotator_raw_impl::~annotator_raw_impl() {}
55 
add_tag(uint64_t offset,pmt_t key,pmt_t val)56 void annotator_raw_impl::add_tag(uint64_t offset, pmt_t key, pmt_t val)
57 {
58     gr::thread::scoped_lock l(d_mutex);
59 
60     tag_t tag;
61     tag.srcid = pmt::intern(name());
62     tag.key = key;
63     tag.value = val;
64     tag.offset = offset;
65 
66     // add our new tag
67     d_queued_tags.push_back(tag);
68     // make sure our tags are in offset order
69     std::sort(d_queued_tags.begin(), d_queued_tags.end(), tag_t::offset_compare);
70     // make sure we are not adding an item in the past!
71     if (tag.offset > nitems_read(0)) {
72         throw std::runtime_error(
73             "annotator_raw::add_tag: item added too far in the past\n.");
74     }
75 }
76 
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)77 int annotator_raw_impl::work(int noutput_items,
78                              gr_vector_const_void_star& input_items,
79                              gr_vector_void_star& output_items)
80 {
81     gr::thread::scoped_lock l(d_mutex);
82 
83     const char* in = (const char*)input_items[0];
84     char* out = (char*)output_items[0];
85 
86     uint64_t start_N = nitems_read(0);
87     uint64_t end_N = start_N + (uint64_t)(noutput_items);
88 
89     // locate queued tags that fall in this range and insert them when appropriate
90     std::vector<tag_t>::iterator i = d_queued_tags.begin();
91     while (i != d_queued_tags.end()) {
92         if ((*i).offset >= start_N && (*i).offset < end_N) {
93             add_item_tag(0, (*i).offset, (*i).key, (*i).value, (*i).srcid);
94             i = d_queued_tags.erase(i);
95         } else {
96             break;
97         }
98     }
99 
100     // copy data across
101     memcpy(out, in, noutput_items * d_itemsize);
102     return noutput_items;
103 }
104 
105 } /* namespace blocks */
106 } /* namespace gr */
107