summaryrefslogtreecommitdiff
path: root/gr-blocks/lib
diff options
context:
space:
mode:
authorJohnathan Corgan <johnathan@corganlabs.com>2013-03-15 09:57:31 -0700
committerJohnathan Corgan <johnathan@corganlabs.com>2013-03-15 09:57:31 -0700
commite965a5bb209ad46a509ccd21f393667fd69d95f9 (patch)
tree40d683ef8f80980f12eac6cfe7f3423c49b45f87 /gr-blocks/lib
parent2bf9c4cb4b0b426690f353fc1662a13e70c0d5e0 (diff)
parent27990ca9e236931e39a830e48f0a1efe13ec085f (diff)
Merge branch 'ofdm-master' into ofdm-next
Added fixups for next branch changes Conflicts: CMakeLists.txt gnuradio-core/src/lib/io/gr_message_sink.cc gnuradio-core/src/lib/io/gr_message_sink.h gnuradio-core/src/lib/io/gr_message_sink.i gnuradio-core/src/lib/io/gr_message_source.cc gnuradio-core/src/lib/io/gr_message_source.h gnuradio-core/src/lib/io/gr_message_source.i gr-blocks/CMakeLists.txt gr-digital/CMakeLists.txt gr-digital/grc/digital_block_tree.xml gr-digital/include/digital/CMakeLists.txt gr-digital/include/digital_ofdm_cyclic_prefixer.h gr-digital/lib/CMakeLists.txt gr-digital/lib/digital_ofdm_cyclic_prefixer.cc gr-digital/lib/ofdm_cyclic_prefixer_impl.h gr-digital/python/CMakeLists.txt gr-digital/swig/CMakeLists.txt gr-digital/swig/digital_swig.i
Diffstat (limited to 'gr-blocks/lib')
-rw-r--r--gr-blocks/lib/CMakeLists.txt6
-rw-r--r--gr-blocks/lib/message_sink_impl.cc79
-rw-r--r--gr-blocks/lib/message_sink_impl.h6
-rw-r--r--gr-blocks/lib/message_source_impl.cc100
-rw-r--r--gr-blocks/lib/message_source_impl.h6
-rw-r--r--gr-blocks/lib/repack_bits_bb_impl.cc123
-rw-r--r--gr-blocks/lib/repack_bits_bb_impl.h58
-rw-r--r--gr-blocks/lib/tagged_stream_mux_impl.cc93
-rw-r--r--gr-blocks/lib/tagged_stream_mux_impl.h54
9 files changed, 470 insertions, 55 deletions
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index c7a7b6362f..b6ad772d29 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -91,8 +91,8 @@ endmacro(expand_cc_h_impl)
# Invoke macro to generate various sources
########################################################################
expand_cc_h_impl(add_XX ss ii cc)
-expand_cc_h_impl(add_const_XX ss ii ff cc)
-expand_cc_h_impl(add_const_vXX ss ii ff cc)
+expand_cc_h_impl(add_const_XX bb ss ii ff cc)
+expand_cc_h_impl(add_const_vXX bb ss ii ff cc)
expand_cc_h_impl(and_XX bb ss ii)
expand_cc_h_impl(and_const_XX bb ss ii)
expand_cc_h_impl(argmax_XX fs is ss)
@@ -200,6 +200,7 @@ list(APPEND gr_blocks_sources
random_pdu_impl.cc
probe_rate_impl.cc
regenerate_bb_impl.cc
+ repack_bits_bb_impl.cc
repeat_impl.cc
rms_cf_impl.cc
rms_ff_impl.cc
@@ -220,6 +221,7 @@ list(APPEND gr_blocks_sources
transcendental_impl.cc
tcp_connection.cc
tuntap_pdu_impl.cc
+ tagged_stream_mux_impl.cc
uchar_array_to_float.cc
uchar_to_float_impl.cc
udp_sink_impl.cc
diff --git a/gr-blocks/lib/message_sink_impl.cc b/gr-blocks/lib/message_sink_impl.cc
index a8dbfb4c71..fbc7b27d58 100644
--- a/gr-blocks/lib/message_sink_impl.cc
+++ b/gr-blocks/lib/message_sink_impl.cc
@@ -44,11 +44,30 @@ namespace gr {
(new message_sink_impl(itemsize, msgq, dont_block));
}
+ message_sink::sptr
+ message_sink::make(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname)
+ {
+ return gnuradio::get_initial_sptr
+ (new message_sink_impl(itemsize, msgq, dont_block, lengthtagname));
+ }
+
message_sink_impl::message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block)
: gr_sync_block("message_sink",
gr_make_io_signature(1, 1, itemsize),
gr_make_io_signature(0, 0, 0)),
- d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block)
+ d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block),
+ d_tags(false), d_items_read(0)
+ {
+ }
+
+ message_sink_impl::message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname)
+ : gr_sync_block("message_sink",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(0, 0, 0)),
+ d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block),
+ d_tags(true), d_lengthtagname(lengthtagname), d_items_read(0)
{
}
@@ -61,23 +80,53 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- const char *in = (const char*)input_items[0];
-
- // if we'd block, drop the data on the floor and say everything is OK
- if(d_dont_block && d_msgq->full_p())
- return noutput_items;
-
- // build a message to hold whatever we've got
- gr_message_sptr msg = gr_make_message(0, // msg type
- d_itemsize, // arg1 for other end
- noutput_items, // arg2 for other end (redundant)
- noutput_items * d_itemsize); // len of msg
- memcpy(msg->msg(), in, noutput_items * d_itemsize);
+ const char *in = (const char *) input_items[0];
- d_msgq->handle(msg); // send it
+ if (d_tags) {
+ long packet_length = 0;
+ std::vector<gr_tag_t> tags;
+ this->get_tags_in_range(tags, 0, d_items_read, d_items_read+1);
+ //const size_t ninput_items = noutput_items; //assumption for sync block, this can change
+ for (unsigned int i = 0; i < tags.size(); i++) {
+ if (pmt::symbol_to_string(tags[i].key) == d_lengthtagname) {
+ packet_length = pmt::to_long(tags[i].value);
+ }
+ }
+ assert(packet_length != 0);
+
+ // FIXME run this multiple times if input_items >= N * packet_length
+ if (noutput_items >= packet_length ) {
+ // If the message queue is full we drop the packet.
+ if (!d_msgq->full_p()) {
+ gr_message_sptr msg = gr_make_message(0, // msg type
+ d_itemsize, // arg1 for other end
+ packet_length, // arg2 for other end (redundant)
+ packet_length * d_itemsize); // len of msg
+ memcpy(msg->msg(), in, packet_length * d_itemsize);
+ d_msgq->handle(msg); // send it
+ }
+ d_items_read += packet_length;
+ return packet_length;
+ } else {
+ return 0;
+ }
+ } else {
+ // If the queue if full we drop all the data we got.
+ if (!d_msgq->full_p()) {
+ // build a message to hold whatever we've got
+ gr_message_sptr msg = gr_make_message(0, // msg type
+ d_itemsize, // arg1 for other end
+ noutput_items, // arg2 for other end (redundant)
+ noutput_items * d_itemsize); // len of msg
+ memcpy(msg->msg(), in, noutput_items * d_itemsize);
+
+ d_msgq->handle(msg); // send it
+ }
- return noutput_items;
+ return noutput_items;
+ }
}
} /* namespace blocks */
} /* namespace gr */
+
diff --git a/gr-blocks/lib/message_sink_impl.h b/gr-blocks/lib/message_sink_impl.h
index a3106bc058..280a46765e 100644
--- a/gr-blocks/lib/message_sink_impl.h
+++ b/gr-blocks/lib/message_sink_impl.h
@@ -34,9 +34,15 @@ namespace gr {
size_t d_itemsize;
gr_msg_queue_sptr d_msgq;
bool d_dont_block;
+ bool d_tags;
+ std::string d_lengthtagname;
+ uint64_t d_items_read;
public:
message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block);
+ message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname);
+
~message_sink_impl();
int work(int noutput_items,
diff --git a/gr-blocks/lib/message_source_impl.cc b/gr-blocks/lib/message_source_impl.cc
index cda4fc16c0..818cd336f1 100644
--- a/gr-blocks/lib/message_source_impl.cc
+++ b/gr-blocks/lib/message_source_impl.cc
@@ -51,12 +51,20 @@ namespace gr {
(new message_source_impl(itemsize, msgq));
}
+ message_source::sptr
+ message_source::make(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname)
+ {
+ return gnuradio::get_initial_sptr
+ (new message_source_impl(itemsize, msgq, lengthtagname));
+ }
+
message_source_impl::message_source_impl(size_t itemsize, int msgq_limit)
: gr_sync_block("message_source",
gr_make_io_signature(0, 0, 0),
gr_make_io_signature(1, 1, itemsize)),
d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)),
- d_msg_offset(0), d_eof(false)
+ d_msg_offset(0), d_eof(false), d_tags(false)
{
}
@@ -65,7 +73,17 @@ namespace gr {
gr_make_io_signature(0, 0, 0),
gr_make_io_signature(1, 1, itemsize)),
d_itemsize(itemsize), d_msgq(msgq),
- d_msg_offset(0), d_eof(false)
+ d_msg_offset(0), d_eof(false), d_tags(false)
+ {
+ }
+
+ message_source_impl::message_source_impl(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname)
+ : gr_sync_block("message_source",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false),
+ d_tags(true), d_lengthtagname(lengthtagname)
{
}
@@ -82,42 +100,48 @@ namespace gr {
int nn = 0;
while(nn < noutput_items) {
- if(d_msg) {
- //
- // Consume whatever we can from the current message
- //
- int mm = std::min(noutput_items - nn,
- (int)((d_msg->length() - d_msg_offset) / d_itemsize));
- memcpy(out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize);
-
- nn += mm;
- out += mm * d_itemsize;
- d_msg_offset += mm * d_itemsize;
- assert(d_msg_offset <= d_msg->length());
-
- if(d_msg_offset == d_msg->length()) {
- if(d_msg->type() == 1) // type == 1 sets EOF
- d_eof = true;
- d_msg.reset();
- }
- }
- else {
- //
- // No current message
- //
- if(d_msgq->empty_p() && nn > 0) { // no more messages in the queue, return what we've got
- break;
- }
-
- if(d_eof)
- return -1;
-
- d_msg = d_msgq->delete_head(); // block, waiting for a message
- d_msg_offset = 0;
-
- if((d_msg->length() % d_itemsize) != 0)
- throw std::runtime_error("msg length is not a multiple of d_itemsize");
- }
+ if (d_msg){
+ //
+ // Consume whatever we can from the current message
+ //
+ int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize));
+ memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize);
+
+ if (d_tags && (d_msg_offset == 0)) {
+ const uint64_t offset = this->nitems_written(0) + nn;
+ pmt::pmt_t key = pmt::string_to_symbol(d_lengthtagname);
+ pmt::pmt_t value = pmt::from_long(d_msg->length());
+ this->add_item_tag(0, offset, key, value);
+ }
+ nn += mm;
+ out += mm * d_itemsize;
+ d_msg_offset += mm * d_itemsize;
+ assert(d_msg_offset <= d_msg->length());
+
+ if (d_msg_offset == d_msg->length()){
+ if (d_msg->type() == 1) // type == 1 sets EOF
+ d_eof = true;
+ d_msg.reset();
+ }
+ }
+ else {
+ //
+ // No current message
+ //
+ if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got
+ break;
+ }
+
+ if (d_eof)
+ return -1;
+
+ d_msg = d_msgq->delete_head(); // block, waiting for a message
+ d_msg_offset = 0;
+
+ if ((d_msg->length() % d_itemsize) != 0)
+ throw std::runtime_error("msg length is not a multiple of d_itemsize");
+ }
+
}
return nn;
diff --git a/gr-blocks/lib/message_source_impl.h b/gr-blocks/lib/message_source_impl.h
index c420704478..8fbd209e0a 100644
--- a/gr-blocks/lib/message_source_impl.h
+++ b/gr-blocks/lib/message_source_impl.h
@@ -37,10 +37,16 @@ namespace gr {
gr_message_sptr d_msg;
unsigned d_msg_offset;
bool d_eof;
+ bool d_tags;
+ // FIXME: Is this adequate tagname length.
+ std::string d_lengthtagname;
public:
message_source_impl(size_t itemsize, int msgq_limit);
message_source_impl(size_t itemsize, gr_msg_queue_sptr msgq);
+ message_source_impl(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname);
+
~message_source_impl();
gr_msg_queue_sptr msgq() const { return d_msgq; }
diff --git a/gr-blocks/lib/repack_bits_bb_impl.cc b/gr-blocks/lib/repack_bits_bb_impl.cc
new file mode 100644
index 0000000000..c7ed054c8a
--- /dev/null
+++ b/gr-blocks/lib/repack_bits_bb_impl.cc
@@ -0,0 +1,123 @@
+/* -*- 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_io_signature.h>
+#include "repack_bits_bb_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ repack_bits_bb::sptr
+ repack_bits_bb::make(int k, int l, const std::string &len_tag_key, bool align_output)
+ {
+ return gnuradio::get_initial_sptr (new repack_bits_bb_impl(k, l, len_tag_key, align_output));
+ }
+
+ repack_bits_bb_impl::repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output)
+ : gr_tagged_stream_block("repack_bits_bb",
+ gr_make_io_signature(1, 1, sizeof (char)),
+ gr_make_io_signature(1, 1, sizeof (char)),
+ len_tag_key),
+ d_k(k), d_l(l),
+ d_packet_mode(!len_tag_key.empty()),
+ d_in_index(0), d_out_index(0),
+ d_align_output(align_output)
+ {
+ if (d_k > 8 || d_k < 1 || d_l > 8 || d_l < 1) {
+ throw std::invalid_argument("k and l must be in [1, 8]");
+ }
+
+ set_relative_rate((double) d_k / d_l);
+ }
+
+ repack_bits_bb_impl::~repack_bits_bb_impl()
+ {
+ }
+
+ int
+ repack_bits_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int n_out_bytes_required = (ninput_items[0] * d_k) / d_l;
+ if ((ninput_items[0] * d_k) % d_l && (!d_packet_mode || (d_packet_mode && !d_align_output))) {
+ n_out_bytes_required++;
+ }
+
+ return n_out_bytes_required;
+ }
+
+ int
+ repack_bits_bb_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+ int bytes_to_write = noutput_items;
+
+ if (d_packet_mode) { // noutput_items could be larger than necessary
+ int bytes_to_read = ninput_items[0];
+ bytes_to_write = bytes_to_read * d_k / d_l;
+ if (!d_align_output && (((bytes_to_read * d_k) % d_l) != 0)) {
+ bytes_to_write++;
+ }
+ }
+
+ int n_read = 0;
+ int n_written = 0;
+ while(n_written < bytes_to_write && n_read < ninput_items[0]) {
+ if (d_out_index == 0) { // Starting a fresh byte
+ out[n_written] = 0;
+ }
+ out[n_written] |= ((in[n_read] >> d_in_index) & 0x01) << d_out_index;
+
+ d_in_index = (d_in_index + 1) % d_k;
+ d_out_index = (d_out_index + 1) % d_l;
+ if (d_in_index == 0) {
+ n_read++;
+ d_in_index = 0;
+ }
+ if (d_out_index == 0) {
+ n_written++;
+ d_out_index = 0;
+ }
+ }
+
+ if (d_packet_mode) {
+ if (d_out_index) {
+ n_written++;
+ d_out_index = 0;
+ }
+ } else {
+ consume_each(n_read);
+ }
+
+ return n_written;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/repack_bits_bb_impl.h b/gr-blocks/lib/repack_bits_bb_impl.h
new file mode 100644
index 0000000000..bf39f8cb0f
--- /dev/null
+++ b/gr-blocks/lib/repack_bits_bb_impl.h
@@ -0,0 +1,58 @@
+/* -*- 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_BLOCKS_REPACK_BITS_BB_IMPL_H
+#define INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H
+
+#include <blocks/repack_bits_bb.h>
+
+namespace gr {
+ namespace blocks {
+
+ class repack_bits_bb_impl : public repack_bits_bb
+ {
+ private:
+ const int d_k; //! Bits on input stream
+ const int d_l; //! Bits on output stream
+ const bool d_packet_mode;
+ int d_in_index; // Current bit of input byte
+ int d_out_index; // Current bit of output byte
+ bool d_align_output; //! true if the output shall be aligned, false if the input shall be aligned
+
+ protected:
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ public:
+ repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output);
+ ~repack_bits_bb_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H */
+
diff --git a/gr-blocks/lib/tagged_stream_mux_impl.cc b/gr-blocks/lib/tagged_stream_mux_impl.cc
new file mode 100644
index 0000000000..59e36fa07e
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_mux_impl.cc
@@ -0,0 +1,93 @@
+/* -*- 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_io_signature.h>
+#include "tagged_stream_mux_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ tagged_stream_mux::sptr
+ tagged_stream_mux::make(size_t itemsize, const std::string &lengthtagname)
+ {
+ return gnuradio::get_initial_sptr (new tagged_stream_mux_impl(itemsize, lengthtagname));
+ }
+
+ tagged_stream_mux_impl::tagged_stream_mux_impl(size_t itemsize, const std::string &lengthtagname)
+ : gr_tagged_stream_block("tagged_stream_mux",
+ gr_make_io_signature(1, -1, itemsize),
+ gr_make_io_signature(1, 1, itemsize),
+ lengthtagname),
+ d_itemsize(itemsize)
+ {
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ tagged_stream_mux_impl::~tagged_stream_mux_impl()
+ {
+ }
+
+ int
+ tagged_stream_mux_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int nout = 0;
+ for (unsigned i = 0; i < ninput_items.size(); i++) {
+ nout += ninput_items[i];
+ }
+ return nout;
+ }
+
+ int
+ tagged_stream_mux_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ unsigned char *out = (unsigned char *) output_items[0];
+ int n_produced = 0;
+
+ set_relative_rate(ninput_items.size());
+
+ for (unsigned int i = 0; i < input_items.size(); i++) {
+ const unsigned char *in = (const unsigned char *) input_items[i];
+
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, i, nitems_read(i), nitems_read(i)+ninput_items[i]);
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ const uint64_t offset = tags[j].offset - nitems_read(i) + nitems_written(0) + n_produced;
+ add_item_tag(0, offset, tags[j].key, tags[j].value);
+ }
+ memcpy((void *) out, (const void *) in, ninput_items[i] * d_itemsize);
+ out += ninput_items[i] * d_itemsize;
+ n_produced += ninput_items[i];
+ }
+
+ return n_produced;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/tagged_stream_mux_impl.h b/gr-blocks/lib/tagged_stream_mux_impl.h
new file mode 100644
index 0000000000..19862e6868
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_mux_impl.h
@@ -0,0 +1,54 @@
+/* -*- 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_TAGGED_STREAM_MUX_IMPL_H
+#define INCLUDED_TAGGED_STREAM_MUX_IMPL_H
+
+#include <vector>
+#include <blocks/tagged_stream_mux.h>
+
+namespace gr {
+ namespace blocks {
+
+ class tagged_stream_mux_impl : public tagged_stream_mux
+ {
+ private:
+ size_t d_itemsize;
+
+ protected:
+ int calculate_output_stream_length(const std::vector<int> &ninput_items);
+
+ public:
+ tagged_stream_mux_impl(size_t itemsize, const std::string &lengthtagname);
+ ~tagged_stream_mux_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif
+