summaryrefslogtreecommitdiff
path: root/gnuradio-runtime
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime')
-rw-r--r--gnuradio-runtime/include/gnuradio/basic_block.h31
-rw-r--r--gnuradio-runtime/include/gnuradio/block_registry.h3
-rw-r--r--gnuradio-runtime/include/gnuradio/logger.h.in30
-rw-r--r--gnuradio-runtime/include/pmt/pmt_sugar.h10
-rw-r--r--gnuradio-runtime/lib/basic_block.cc27
-rw-r--r--gnuradio-runtime/lib/block.cc2
-rw-r--r--gnuradio-runtime/lib/block_registry.cc20
-rw-r--r--gnuradio-runtime/lib/flowgraph.cc8
-rwxr-xr-xgnuradio-runtime/lib/pmt/generate_unv.py1
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_int.h1
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_io.cc13
-rw-r--r--gnuradio-runtime/lib/pmt/unv_template.cc.t6
-rw-r--r--gnuradio-runtime/lib/pmt/unv_template.h.t1
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt1
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/__init__.py8
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/packet_utils.py137
-rw-r--r--gnuradio-runtime/python/pmt/pmt_to_python.py7
17 files changed, 273 insertions, 33 deletions
diff --git a/gnuradio-runtime/include/gnuradio/basic_block.h b/gnuradio-runtime/include/gnuradio/basic_block.h
index 69775865ee..b413274ded 100644
--- a/gnuradio-runtime/include/gnuradio/basic_block.h
+++ b/gnuradio-runtime/include/gnuradio/basic_block.h
@@ -144,14 +144,41 @@ namespace gr {
virtual ~basic_block();
long unique_id() const { return d_unique_id; }
long symbolic_id() const { return d_symbolic_id; }
+
+ /*! The name of the block */
std::string name() const { return d_name; }
+
+ /*!
+ * The sybolic name of the block, which is used in the
+ * block_registry. The name is assigned by the block's constructor
+ * and never changes during the life of the block.
+ */
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; }
basic_block_sptr to_basic_block(); // Needed for Python type coercion
+
+ /*!
+ * True if the block has an alias (see set_block_alias).
+ */
bool alias_set() { return !d_symbol_alias.empty(); }
+
+ /*!
+ * Returns the block's alias as a string.
+ */
std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
+
+ /*!
+ * Returns the block's alias as PMT.
+ */
pmt::pmt_t alias_pmt(){ return pmt::intern(alias()); }
+
+ /*!
+ * Set's a new alias for the block; also adds an entry into the
+ * block_registry to get the block using either the alias or the
+ * original symbol name.
+ */
void set_block_alias(std::string name);
// ** Message passing interface **
@@ -248,6 +275,10 @@ namespace gr {
}
return false;
}
+
+ const msg_queue_map_t& get_msg_map(void) const {
+ return msg_queue;
+ }
#ifdef GR_CTRLPORT
/*!
diff --git a/gnuradio-runtime/include/gnuradio/block_registry.h b/gnuradio-runtime/include/gnuradio/block_registry.h
index 49f0b7222d..86e5528dd1 100644
--- a/gnuradio-runtime/include/gnuradio/block_registry.h
+++ b/gnuradio-runtime/include/gnuradio/block_registry.h
@@ -44,9 +44,10 @@ namespace gr {
std::string register_symbolic_name(basic_block* block);
void register_symbolic_name(basic_block* block, std::string name);
+ void update_symbolic_name(basic_block* block, std::string name);
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);
diff --git a/gnuradio-runtime/include/gnuradio/logger.h.in b/gnuradio-runtime/include/gnuradio/logger.h.in
index 17afa7effd..8e8cd2fb1e 100644
--- a/gnuradio-runtime/include/gnuradio/logger.h.in
+++ b/gnuradio-runtime/include/gnuradio/logger.h.in
@@ -1,19 +1,19 @@
/* -*- c++ -*- */
/*
* Copyright 2012-2013 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,
@@ -69,9 +69,9 @@ namespace gr {
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
#define GR_CONFIG_LOGGER(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
-#define GR_LOG_GETLOGGER(logger, name)
+#define GR_LOG_GETLOGGER(logger, name)
#define GR_SET_LEVEL(name, level)
-#define GR_LOG_SET_LEVEL(logger, level)
+#define GR_LOG_SET_LEVEL(logger, level)
#define GR_GET_LEVEL(name, level)
#define GR_LOG_GET_LEVEL(logger, level)
#define GR_ADD_APPENDER(name,appender)
@@ -326,11 +326,11 @@ namespace gr {
namespace gr {
/*!
- * \brief Class to control configuration of logger.
+ * \brief Class to control configuration of logger.
* This is a singleton that cna launch a thread to wathc a config file for changes
* \ingroup logging
*/
- class logger_config
+ class GR_RUNTIME_API logger_config
{
private:
/*! \brief filename of logger config file */
@@ -340,7 +340,7 @@ namespace gr {
/*! \brief Pointer to watch thread for config file changes */
boost::thread *watch_thread;
- /*! \brief Watcher thread method
+ /*! \brief Watcher thread method
* /param filename Name of configuration file
* /param watch_period Seconds between checks for changes in config file
*/
@@ -632,7 +632,7 @@ namespace gr {
*
* Add rolling file appender to a given logger
*
- * \return vector of string names of loggers
+ * \return vector of string names of loggers
*/
GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void);
@@ -651,9 +651,9 @@ namespace gr {
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
#define GR_CONFIG_LOGGER(config)
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
-#define GR_LOG_GETLOGGER(logger, name)
+#define GR_LOG_GETLOGGER(logger, name)
#define GR_SET_LEVEL(name, level)
-#define GR_LOG_SET_LEVEL(logger, level)
+#define GR_LOG_SET_LEVEL(logger, level)
#define GR_GET_LEVEL(name, level)
#define GR_LOG_GET_LEVEL(logger, level)
#define GR_ADD_APPENDER(name,appender)
@@ -710,7 +710,7 @@ namespace gr {
* \ingroup logging
*
*/
- class logger
+ class GR_RUNTIME_API logger
{
private:
/*! \brief logger pointer to logger associated wiith this wrapper class */
@@ -812,7 +812,7 @@ namespace gr {
/**************** Start Configuration Class and Methods for Python ************/
/*!
- * \brief Function to call configuration macro from python.
+ * \brief Function to call configuration macro from python.
* Note: Configuration is only updated if filename or watch_period has changed.
* \param config_filename Name of configuration file
* \param watch_period Seconds to wait between checking for changes in conf file.
@@ -830,7 +830,7 @@ GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void);
/*!
* \brief Function to reset logger configuration from python
- *
+ *
*/
GR_RUNTIME_API void gr_logger_reset_config(void);
diff --git a/gnuradio-runtime/include/pmt/pmt_sugar.h b/gnuradio-runtime/include/pmt/pmt_sugar.h
index 870b81902e..424f85cb01 100644
--- a/gnuradio-runtime/include/pmt/pmt_sugar.h
+++ b/gnuradio-runtime/include/pmt/pmt_sugar.h
@@ -51,10 +51,16 @@ namespace pmt {
return from_long(x);
}
- //! Make pmt long
+ //! Make pmt uint64
+ static inline pmt_t
+ mp(long unsigned x){
+ return from_uint64(x);
+ }
+
+ //! Make pmt uint64
static inline pmt_t
mp(long long unsigned x){
- return from_long(x);
+ return from_uint64(x);
}
//! Make pmt long
diff --git a/gnuradio-runtime/lib/basic_block.cc b/gnuradio-runtime/lib/basic_block.cc
index 40edf09b01..686c1d6e65 100644
--- a/gnuradio-runtime/lib/basic_block.cc
+++ b/gnuradio-runtime/lib/basic_block.cc
@@ -71,8 +71,17 @@ namespace gr {
void
basic_block::set_block_alias(std::string name)
- {
- global_block_registry.register_symbolic_name(this, name);
+ {
+ // Only keep one alias'd name around for each block. If we don't
+ // have an alias, add it; if we do, update the entry in the
+ // registry.
+ if(alias_set())
+ global_block_registry.update_symbolic_name(this, name);
+ else
+ global_block_registry.register_symbolic_name(this, name);
+
+ // set the block's alias
+ d_symbol_alias = name;
}
// ** Message passing interface **
@@ -131,7 +140,7 @@ namespace gr {
if(!pmt::dict_has_key(d_message_subscribers, port_id)) {
throw std::runtime_error("port does not exist");
}
-
+
pmt::pmt_t currlist = pmt::dict_ref(d_message_subscribers, port_id, pmt::PMT_NIL);
// iterate through subscribers on port
while(pmt::is_pair(currlist)) {
@@ -139,7 +148,7 @@ namespace gr {
pmt::pmt_t block = pmt::car(target);
pmt::pmt_t port = pmt::cdr(target);
-
+
currlist = pmt::cdr(currlist);
basic_block_sptr blk = global_block_registry.block_lookup(block);
//blk->post(msg);
@@ -150,14 +159,14 @@ namespace gr {
// - subscribe to a message port
void
basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){
- if(!pmt::dict_has_key(d_message_subscribers, port_id)){
+ if(!pmt::dict_has_key(d_message_subscribers, port_id)){
std::stringstream ss;
ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: "
<< pmt::write_string(target) << std::endl;
throw std::runtime_error(ss.str());
}
pmt::pmt_t currlist = pmt::dict_ref(d_message_subscribers,port_id,pmt::PMT_NIL);
-
+
// ignore re-adds of the same target
if(!pmt::list_has(currlist, target))
d_message_subscribers = pmt::dict_add(d_message_subscribers,port_id,pmt::list_add(currlist,target));
@@ -166,13 +175,13 @@ namespace gr {
void
basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target)
{
- if(!pmt::dict_has_key(d_message_subscribers, port_id)) {
+ if(!pmt::dict_has_key(d_message_subscribers, port_id)) {
std::stringstream ss;
ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: "
<< pmt::write_string(target) << std::endl;
throw std::runtime_error(ss.str());
}
-
+
// ignore unsubs of unknown targets
pmt::pmt_t currlist = pmt::dict_ref(d_message_subscribers,port_id,pmt::PMT_NIL);
d_message_subscribers = pmt::dict_add(d_message_subscribers,port_id,pmt::list_rm(currlist,target));
@@ -230,7 +239,7 @@ namespace gr {
return m;
}
- pmt::pmt_t
+ pmt::pmt_t
basic_block::message_subscribers(pmt::pmt_t port)
{
return pmt::dict_ref(d_message_subscribers,port,pmt::PMT_NIL);
diff --git a/gnuradio-runtime/lib/block.cc b/gnuradio-runtime/lib/block.cc
index 9e4fcf5cca..6309bca9b1 100644
--- a/gnuradio-runtime/lib/block.cc
+++ b/gnuradio-runtime/lib/block.cc
@@ -111,7 +111,7 @@ namespace gr {
block::~block()
{
- global_block_registry.unregister_primitive(alias());
+ global_block_registry.unregister_primitive(symbol_name());
}
unsigned
diff --git a/gnuradio-runtime/lib/block_registry.cc b/gnuradio-runtime/lib/block_registry.cc
index c4dc7647d6..5241ef9922 100644
--- a/gnuradio-runtime/lib/block_registry.cc
+++ b/gnuradio-runtime/lib/block_registry.cc
@@ -90,6 +90,26 @@ namespace gr {
d_ref_map = pmt::dict_add(d_ref_map, pmt::intern(name), pmt::make_any(block));
}
+ void
+ block_registry::update_symbolic_name(basic_block* block, std::string name)
+ {
+ gr::thread::scoped_lock guard(d_mutex);
+
+ if(pmt::dict_has_key(d_ref_map, pmt::intern(name))) {
+ throw std::runtime_error("symbol already exists, can not re-use!");
+ }
+
+ // If we don't already have an alias, don't try and delete it.
+ if(block->alias_set()) {
+ // And make sure that the registry has the alias key.
+ // We test both in case the block's and registry ever get out of sync.
+ if(pmt::dict_has_key(d_ref_map, block->alias_pmt())) {
+ d_ref_map = pmt::dict_delete(d_ref_map, block->alias_pmt());
+ }
+ }
+ d_ref_map = pmt::dict_add(d_ref_map, pmt::intern(name), pmt::make_any(block));
+ }
+
basic_block_sptr
block_registry::block_lookup(pmt::pmt_t symbol)
{
diff --git a/gnuradio-runtime/lib/flowgraph.cc b/gnuradio-runtime/lib/flowgraph.cc
index 3d8dfea65a..abe51f741d 100644
--- a/gnuradio-runtime/lib/flowgraph.cc
+++ b/gnuradio-runtime/lib/flowgraph.cc
@@ -155,8 +155,14 @@ namespace gr {
if(FLOWGRAPH_DEBUG)
std::cout << "check_valid_port( " << e.block() << ", " << e.port() << ")\n";
- if(!e.block()->has_msg_port(e.port()))
+ if(!e.block()->has_msg_port(e.port())) {
+ const gr::basic_block::msg_queue_map_t& msg_map = e.block()->get_msg_map();
+ std::cout << "Could not find port: " << e.port() << " in:" << std::endl;
+ for (gr::basic_block::msg_queue_map_t::const_iterator it = msg_map.begin(); it != msg_map.end(); ++it)
+ std::cout << it->first << std::endl;
+ std::cout << std::endl;
throw std::invalid_argument("invalid msg port in connect() or disconnect()");
+ }
}
void
diff --git a/gnuradio-runtime/lib/pmt/generate_unv.py b/gnuradio-runtime/lib/pmt/generate_unv.py
index 7562df46f8..6218099fc1 100755
--- a/gnuradio-runtime/lib/pmt/generate_unv.py
+++ b/gnuradio-runtime/lib/pmt/generate_unv.py
@@ -76,6 +76,7 @@ includes = """
#endif
#include <vector>
#include <pmt/pmt.h>
+#include <boost/lexical_cast.hpp>
#include "pmt_int.h"
"""
diff --git a/gnuradio-runtime/lib/pmt/pmt_int.h b/gnuradio-runtime/lib/pmt/pmt_int.h
index ca90c5a475..49bde52063 100644
--- a/gnuradio-runtime/lib/pmt/pmt_int.h
+++ b/gnuradio-runtime/lib/pmt/pmt_int.h
@@ -239,6 +239,7 @@ public:
virtual void *uniform_writable_elements(size_t &len) = 0;
virtual size_t length() const = 0;
virtual size_t itemsize() const = 0;
+ virtual const std::string string_ref(size_t k) const { return std::string("not implemented"); }
};
#include "pmt_unv_int.h"
diff --git a/gnuradio-runtime/lib/pmt/pmt_io.cc b/gnuradio-runtime/lib/pmt/pmt_io.cc
index 17bdee408f..e63bae4994 100644
--- a/gnuradio-runtime/lib/pmt/pmt_io.cc
+++ b/gnuradio-runtime/lib/pmt/pmt_io.cc
@@ -110,9 +110,16 @@ write(pmt_t obj, std::ostream &port)
port << "#<dict>";
}
else if (is_uniform_vector(obj)){
- // FIXME
- // port << "#<uniform-vector " << obj << ">";
- port << "#<uniform-vector>";
+ port << "#[";
+ size_t len = length(obj);
+ if (len)
+ {
+ pmt_uniform_vector *uv = static_cast<pmt_uniform_vector*>(obj.get());
+ port << uv->string_ref(0);
+ for (size_t i = 1; i < len; i++)
+ port << " " << uv->string_ref(i);
+ }
+ port << "]";
}
else {
error:
diff --git a/gnuradio-runtime/lib/pmt/unv_template.cc.t b/gnuradio-runtime/lib/pmt/unv_template.cc.t
index 8678894973..c8020e7de2 100644
--- a/gnuradio-runtime/lib/pmt/unv_template.cc.t
+++ b/gnuradio-runtime/lib/pmt/unv_template.cc.t
@@ -138,4 +138,10 @@ const std::vector< @TYPE@ >
return _@TAG@vector(vector)->writable_elements(len);
}
+const std::string
+pmt_@TAG@vector::string_ref(size_t k) const
+{
+ return boost::lexical_cast< std::string, @TYPE@ > (ref(k));
+}
+
} /* namespace pmt */
diff --git a/gnuradio-runtime/lib/pmt/unv_template.h.t b/gnuradio-runtime/lib/pmt/unv_template.h.t
index 93ca684463..ab5c163570 100644
--- a/gnuradio-runtime/lib/pmt/unv_template.h.t
+++ b/gnuradio-runtime/lib/pmt/unv_template.h.t
@@ -21,4 +21,5 @@ public:
@TYPE@ *writable_elements(size_t &len);
const void *uniform_elements(size_t &len);
void *uniform_writable_elements(size_t &len);
+ virtual const std::string string_ref(size_t k) const;
};
diff --git a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
index 9d6f4dd718..ddad2c448a 100644
--- a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
+++ b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
@@ -23,6 +23,7 @@ include(GrPython)
GR_PYTHON_INSTALL(FILES
__init__.py
tag_utils.py
+ packet_utils.py
gateway.py
gr_threading.py
gr_threading_23.py
diff --git a/gnuradio-runtime/python/gnuradio/gr/__init__.py b/gnuradio-runtime/python/gnuradio/gr/__init__.py
index 94a5c9ec2b..4fc55c68b2 100644
--- a/gnuradio-runtime/python/gnuradio/gr/__init__.py
+++ b/gnuradio-runtime/python/gnuradio/gr/__init__.py
@@ -48,3 +48,11 @@ from gateway import basic_block, sync_block, decim_block, interp_block
# Force the preference database to be initialized
prefs = prefs.singleton
+
+log = gr.logger("log")
+log.add_console_appender(prefs().get_string("LOG", "log_level", "off"), 'gr::log %d :%p: %m%n')
+log.set_level(prefs().get_string("LOG", "log_level", "notset"))
+
+log_debug = gr.logger("log_debug")
+log_debug.add_console_appender(prefs().get_string("LOG", "debug_level", "off"), 'gr::debug %d :%p: %m%n')
+log_debug.set_level(prefs().get_string("LOG", "debug_level", "notset"))
diff --git a/gnuradio-runtime/python/gnuradio/gr/packet_utils.py b/gnuradio-runtime/python/gnuradio/gr/packet_utils.py
new file mode 100644
index 0000000000..7ae42e88e3
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/packet_utils.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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
+import pmt
+
+def make_lengthtags(lengths, offsets, tagname='length', vlen=1):
+ tags = []
+ assert(len(offsets) == len(lengths))
+ for offset, length in zip(offsets, lengths):
+ tag = gr.tag_t()
+ tag.offset = offset/vlen
+ tag.key = pmt.string_to_symbol(tagname)
+ tag.value = pmt.from_long(length/vlen)
+ tags.append(tag)
+ return tags
+
+def string_to_vector(string):
+ v = []
+ for s in string:
+ v.append(ord(s))
+ return v
+
+def strings_to_vectors(strings, tsb_tag_key):
+ vs = [string_to_vector(string) for string in strings]
+ return packets_to_vectors(vs, tsb_tag_key)
+
+def vector_to_string(v):
+ s = []
+ for d in v:
+ s.append(chr(d))
+ return ''.join(s)
+
+def vectors_to_strings(data, tags, tsb_tag_key):
+ packets = vectors_to_packets(data, tags, tsb_tag_key)
+ return [vector_to_string(packet) for packet in packets]
+
+def count_bursts(data, tags, tsb_tag_key, vlen=1):
+ lengthtags = [t for t in tags
+ if pmt.symbol_to_string(t.key) == tsb_tag_key]
+ lengths = {}
+ for tag in lengthtags:
+ if tag.offset in lengths:
+ raise ValueError(
+ "More than one tags with key {0} with the same offset={1}."
+ .format(tsb_tag_key, tag.offset))
+ lengths[tag.offset] = pmt.to_long(tag.value)*vlen
+ in_burst = False
+ in_packet = False
+ packet_length = None
+ packet_pos = None
+ burst_count = 0
+ for pos in range(len(data)):
+ if pos in lengths:
+ if in_packet:
+ print("Got tag at pos {0} current packet_pos is {1}".format(pos, packet_pos))
+ raise StandardError("Received packet tag while in packet.")
+ packet_pos = -1
+ packet_length = lengths[pos]
+ in_packet = True
+ if not in_burst:
+ burst_count += 1
+ in_burst = True
+ elif not in_packet:
+ in_burst = False
+ if in_packet:
+ packet_pos += 1
+ if packet_pos == packet_length-1:
+ in_packet = False
+ packet_pos = None
+ return burst_count
+
+def vectors_to_packets(data, tags, tsb_tag_key, vlen=1):
+ lengthtags = [t for t in tags
+ if pmt.symbol_to_string(t.key) == tsb_tag_key]
+ lengths = {}
+ for tag in lengthtags:
+ if tag.offset in lengths:
+ raise ValueError(
+ "More than one tags with key {0} with the same offset={1}."
+ .format(tsb_tag_key, tag.offset))
+ lengths[tag.offset] = pmt.to_long(tag.value)*vlen
+ if 0 not in lengths:
+ raise ValueError("There is no tag with key {0} and an offset of 0"
+ .format(tsb_tag_key))
+ pos = 0
+ packets = []
+ while pos < len(data):
+ if pos not in lengths:
+ raise ValueError("There is no tag with key {0} and an offset of {1}."
+ "We were expecting one."
+ .format(tsb_tag_key, pos))
+ length = lengths[pos]
+ if length == 0:
+ raise ValueError("Packets cannot have zero length.")
+ if pos+length > len(data):
+ raise ValueError("The final packet is incomplete.")
+ packets.append(data[pos: pos+length])
+ pos += length
+ return packets
+
+def packets_to_vectors(packets, tsb_tag_key, vlen=1):
+ """ Returns a single data vector and a set of tags.
+ If used with blocks.vector_source_X, this set of data
+ and tags will produced a correct tagged stream. """
+ tags = []
+ data = []
+ offset = 0
+ for packet in packets:
+ data.extend(packet)
+ tag = gr.tag_t()
+ tag.offset = offset/vlen
+ tag.key = pmt.string_to_symbol(tsb_tag_key)
+ tag.value = pmt.from_long(len(packet)/vlen)
+ tags.append(tag)
+ offset = offset + len(packet)
+ return data, tags
+
diff --git a/gnuradio-runtime/python/pmt/pmt_to_python.py b/gnuradio-runtime/python/pmt/pmt_to_python.py
index 3344eba163..8973b886e6 100644
--- a/gnuradio-runtime/python/pmt/pmt_to_python.py
+++ b/gnuradio-runtime/python/pmt/pmt_to_python.py
@@ -110,12 +110,17 @@ type_mappings = ( #python type, check pmt type, to python, from python
(tuple, pmt.is_tuple, pmt_to_tuple, pmt_from_tuple),
(list, pmt.is_vector, pmt_to_vector, pmt_from_vector),
(dict, pmt.is_dict, pmt_to_dict, pmt_from_dict),
+ (tuple, pmt.is_pair, lambda x: (pmt_to_python(pmt.car(x)), pmt_to_python(pmt.cdr(x))), lambda x: pmt.cons(python_to_pmt(x[0]), python_to_pmt(x[1]))),
(numpy.ndarray, pmt.is_uniform_vector, uvector_to_numpy, numpy_to_uvector),
)
def pmt_to_python(p):
for python_type, pmt_check, to_python, from_python in type_mappings:
- if pmt_check(p): return to_python(p)
+ if pmt_check(p):
+ try:
+ return to_python(p)
+ except:
+ pass
raise ValueError("can't convert %s type to pmt (%s)"%(type(p),p))
def python_to_pmt(p):