diff options
59 files changed, 3191 insertions, 104 deletions
diff --git a/config/grc_gnuradio_examples.m4 b/config/grc_gnuradio_examples.m4 index 5b987d617..4e95ea02b 100644 --- a/config/grc_gnuradio_examples.m4 +++ b/config/grc_gnuradio_examples.m4 @@ -22,6 +22,9 @@ AC_DEFUN([GRC_GNURADIO_EXAMPLES],[ AC_CONFIG_FILES([ \ gnuradio-examples/Makefile \ + gnuradio-examples/c++/Makefile \ + gnuradio-examples/c++/dialtone/Makefile \ + gnuradio-examples/c++/hier/Makefile \ gnuradio-examples/python/Makefile \ gnuradio-examples/python/apps/hf_explorer/Makefile \ gnuradio-examples/python/apps/hf_radio/Makefile \ diff --git a/configure.ac b/configure.ac index f3254a33f..bede23767 100644 --- a/configure.ac +++ b/configure.ac @@ -160,7 +160,6 @@ AC_ARG_ENABLE( build_dirs="config" GRC_GNURADIO_CORE -GRC_GNURADIO_EXAMPLES GRC_USRP GRC_GR_USRP dnl this must come after GRC_USRP GRC_GR_AUDIO_ALSA @@ -184,6 +183,7 @@ GRC_MBLOCK dnl this must come after GRC_PMT GRC_EZDOP GRC_GR_EZDOP dnl this must come after GRC_EZDOP GRC_GR_RDF +GRC_GNURADIO_EXAMPLES dnl must come last # Each component is now either to be built, was skipped, or failed dependencies AC_SUBST([build_dirs], [$build_dirs]) diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am index 2c1ea7eff..47ae07a6b 100644 --- a/gnuradio-core/src/lib/runtime/Makefile.am +++ b/gnuradio-core/src/lib/runtime/Makefile.am @@ -30,8 +30,13 @@ libruntime_la_LIBADD = \ libruntime_la_SOURCES = \ + gr_basic_block.cc \ + gr_simple_flowgraph.cc \ + gr_simple_flowgraph_detail.cc \ gr_block.cc \ gr_block_detail.cc \ + gr_hier_block2.cc \ + gr_hier_block2_detail.cc \ gr_buffer.cc \ gr_dispatcher.cc \ gr_error_handler.cc \ @@ -43,6 +48,8 @@ libruntime_la_SOURCES = \ gr_pagesize.cc \ gr_preferences.cc \ gr_realtime.cc \ + gr_runtime.cc \ + gr_runtime_impl.cc \ gr_single_threaded_scheduler.cc \ gr_tmp_path.cc \ gr_vmcircbuf.cc \ @@ -54,14 +61,20 @@ libruntime_la_SOURCES = \ libruntime_qa_la_SOURCES = \ qa_gr_block.cc \ + qa_gr_hier_block2.cc \ qa_gr_buffer.cc \ qa_gr_io_signature.cc \ qa_gr_vmcircbuf.cc \ qa_runtime.cc grinclude_HEADERS = \ + gr_basic_block.h \ + gr_simple_flowgraph.h \ + gr_simple_flowgraph_detail.h \ gr_block.h \ gr_block_detail.h \ + gr_hier_block2.h \ + gr_hier_block2_detail.h \ gr_buffer.h \ gr_complex.h \ gr_dispatcher.h \ @@ -74,6 +87,8 @@ grinclude_HEADERS = \ gr_pagesize.h \ gr_preferences.h \ gr_realtime.h \ + gr_runtime.h \ + gr_runtime_impl.h \ gr_runtime_types.h \ gr_select_handler.h \ gr_single_threaded_scheduler.h \ @@ -88,14 +103,17 @@ noinst_HEADERS = \ gr_vmcircbuf_sysv_shm.h \ gr_vmcircbuf_createfilemapping.h \ qa_gr_block.h \ + qa_gr_hier_block2.h \ qa_gr_buffer.h \ qa_gr_io_signature.h \ qa_gr_vmcircbuf.h \ qa_runtime.h swiginclude_HEADERS = \ + gr_basic_block.i \ gr_block.i \ gr_block_detail.i \ + gr_hier_block2.i \ gr_buffer.i \ gr_dispatcher.i \ gr_error_handler.i \ @@ -104,6 +122,8 @@ swiginclude_HEADERS = \ gr_msg_handler.i \ gr_msg_queue.i \ gr_realtime.i \ + gr_runtime.i \ + gr_simple_flowgraph.i \ gr_single_threaded_scheduler.i \ gr_swig_block_magic.i \ runtime.i diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc new file mode 100644 index 000000000..a5f1a4f83 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_basic_block.h> +#include <stdexcept> + +static long s_next_id = 0; +static long s_ncurrently_allocated = 0; + +long +gr_basic_block_ncurrently_allocated() +{ + return s_ncurrently_allocated; +} + +gr_basic_block::gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : d_name(name), + d_input_signature(input_signature), + d_output_signature(output_signature), + d_unique_id(s_next_id++) +{ + s_ncurrently_allocated++; +} + +gr_basic_block::~gr_basic_block() +{ + s_ncurrently_allocated--; +} + +gr_basic_block_sptr +gr_basic_block::basic_block() +{ + return shared_from_this(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h new file mode 100644 index 000000000..583c3241d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_GR_BASIC_BLOCK_H +#define INCLUDED_GR_BASIC_BLOCK_H + +#include <gr_runtime_types.h> +#include <boost/enable_shared_from_this.hpp> +#include <string> + +/*! + * \brief The abstract base class for all signal processing blocks. + * \ingroup block + * + * Basic blocks are the bare abstraction of an entity that has a name + * and a set of inputs and outputs. These are never instantiated + * directly; rather, this is the abstract parent class of both gr_hier_block, + * which is a recursive container, and gr_block, which implements actual + * signal processing functions. + */ + +class gr_basic_block : public boost::enable_shared_from_this<gr_basic_block> +{ +protected: + std::string d_name; + gr_io_signature_sptr d_input_signature; + gr_io_signature_sptr d_output_signature; + long d_unique_id; + + //! Protected constructor prevents instantiation by non-derived classes + gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + //! may only be called during constructor + void set_input_signature(gr_io_signature_sptr iosig) { + d_input_signature = iosig; + } + + //! may only be called during constructor + void set_output_signature(gr_io_signature_sptr iosig) { + d_output_signature = iosig; + } + +public: + virtual ~gr_basic_block(); + long unique_id() const { return d_unique_id; } + std::string name() const { return d_name; } + gr_io_signature_sptr input_signature() const { return d_input_signature; } + gr_io_signature_sptr output_signature() const { return d_output_signature; } + gr_basic_block_sptr basic_block(); // Needed for Python type coercion + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + virtual bool check_topology(int ninputs, int noutputs) { return true; } +}; + +typedef std::vector<gr_basic_block_sptr> gr_basic_block_vector_t; +typedef std::vector<gr_basic_block_sptr>::iterator gr_basic_block_viter_t; + +long gr_basic_block_ncurrently_allocated(); + +inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block) +{ + os << basic_block->name() << "(" << basic_block->unique_id() << ")"; + return os; +} + +#endif /* INCLUDED_GR_BASIC_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i new file mode 100644 index 000000000..33b895d43 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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. + */ + +class gr_basic_block; +typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; +%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>; + +// support vectors of these... +namespace std { + %template(x_vector_gr_basic_block_sptr) vector<gr_basic_block_sptr>; +}; + +class gr_basic_block +{ +protected: + gr_basic_block(); + +public: + virtual ~gr_basic_block(); + std::string name() const; + gr_io_signature_sptr input_signature() const; + gr_io_signature_sptr output_signature() const; + long unique_id() const; + gr_basic_block_sptr basic_block(); + bool check_topology (int ninputs, int noutputs); +}; + +%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; +long gr_basic_block_ncurrently_allocated(); + +%pythoncode %{ +gr_basic_block_sptr.__repr__ = lambda self: "<gr_basic_block %s (%d)>" % (self.name(), self.unique_id ()) +%} diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index 65e16045a..1b1d35756 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -27,34 +27,21 @@ #include <gr_block.h> #include <gr_block_detail.h> #include <stdexcept> - -static long s_next_id = 0; -static long s_ncurrently_allocated = 0; - -long -gr_block_ncurrently_allocated () -{ - return s_ncurrently_allocated; -} +#include <iostream> gr_block::gr_block (const std::string &name, gr_io_signature_sptr input_signature, gr_io_signature_sptr output_signature) - : d_name (name), - d_input_signature (input_signature), - d_output_signature (output_signature), + : gr_basic_block(name, input_signature, output_signature), d_output_multiple (1), d_relative_rate (1.0), - d_unique_id (s_next_id++), d_history(1), d_fixed_rate(false) { - s_ncurrently_allocated++; } gr_block::~gr_block () { - s_ncurrently_allocated--; } // stub implementation: 1:1 @@ -70,12 +57,6 @@ gr_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) // default implementation bool -gr_block::check_topology (int ninputs, int noutputs) -{ - return true; -} - -bool gr_block::start() { return true; diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index 9723be108..247238bb0 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -23,13 +23,17 @@ #ifndef INCLUDED_GR_BLOCK_H #define INCLUDED_GR_BLOCK_H -#include <gr_runtime_types.h> -#include <string> +#include <gr_basic_block.h> /*! - * \brief The abstract base class for all signal processing blocks. + * \brief The abstract base class for all 'terminal' processing blocks. * \ingroup block * + * A signal processing flow is constructed by creating a tree of + * hierarchical blocks, which at any level may also contain terminal nodes + * that actually implement signal processing functions. This is the base + * class for all such leaf nodes. + * Blocks have a set of input streams and output streams. The * input_signature and output_signature define the number of input * streams and output streams respectively, and the type of the data @@ -49,16 +53,11 @@ * It reads the input items and writes the output items. */ -class gr_block { +class gr_block : public gr_basic_block { public: virtual ~gr_block (); - - std::string name () const { return d_name; } - gr_io_signature_sptr input_signature () const { return d_input_signature; } - gr_io_signature_sptr output_signature () const { return d_output_signature; } - long unique_id () const { return d_unique_id; } /*! * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) @@ -114,21 +113,6 @@ class gr_block { gr_vector_void_star &output_items) = 0; /*! - * \brief Confirm that ninputs and noutputs is an acceptable combination. - * - * \param ninputs number of input streams connected - * \param noutputs number of output streams connected - * - * \returns true if this is a valid configuration for this block. - * - * This function is called by the runtime system whenever the - * topology changes. Most classes do not need to override this. - * This check is in addition to the constraints specified by the input - * and output gr_io_signatures. - */ - virtual bool check_topology (int ninputs, int noutputs); - - /*! * \brief Called to enable drivers, etc for i/o devices. * * This allows a block to enable an associated driver to begin @@ -205,32 +189,17 @@ class gr_block { private: - std::string d_name; - gr_io_signature_sptr d_input_signature; - gr_io_signature_sptr d_output_signature; - int d_output_multiple; - double d_relative_rate; // approx output_rate / input_rate - gr_block_detail_sptr d_detail; // implementation details - long d_unique_id; // convenient for debugging - unsigned d_history; - bool d_fixed_rate; - - + int d_output_multiple; + double d_relative_rate; // approx output_rate / input_rate + gr_block_detail_sptr d_detail; // implementation details + unsigned d_history; + bool d_fixed_rate; + protected: gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - //! may only be called during constructor - void set_input_signature (gr_io_signature_sptr iosig){ - d_input_signature = iosig; - } - - //! may only be called during constructor - void set_output_signature (gr_io_signature_sptr iosig){ - d_output_signature = iosig; - } + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } @@ -242,6 +211,7 @@ class gr_block { void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } }; -long gr_block_ncurrently_allocated (); +typedef std::vector<gr_block_sptr> gr_block_vector_t; +typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t; #endif /* INCLUDED_GR_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i index 3bfd24367..5d0f5fb1b 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.i +++ b/gnuradio-core/src/lib/runtime/gr_block.i @@ -20,6 +20,8 @@ * Boston, MA 02110-1301, USA. */ +%include <gr_basic_block.i> + class gr_block; typedef boost::shared_ptr<gr_block> gr_block_sptr; %template(gr_block_sptr) boost::shared_ptr<gr_block>; @@ -29,26 +31,21 @@ namespace std { %template(x_vector_gr_block_sptr) vector<gr_block_sptr>; }; -class gr_block { +class gr_block : public gr_basic_block { protected: gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); public: virtual ~gr_block (); - std::string name () const; - gr_io_signature_sptr input_signature () const; - gr_io_signature_sptr output_signature () const; - long unique_id () const; unsigned history () const; int output_multiple () const; double relative_rate () const; - bool check_topology (int ninputs, int noutputs); bool start(); bool stop(); @@ -57,9 +54,6 @@ class gr_block { void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } }; -%rename(block_ncurrently_allocated) gr_block_ncurrently_allocated; -long gr_block_ncurrently_allocated (); - %pythoncode %{ gr_block_sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ()) gr_block_sptr.block = lambda self: self diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc index ed414d472..5feb180f7 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -38,7 +38,8 @@ gr_block_detail_ncurrently_allocated () gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs) : d_ninputs (ninputs), d_noutputs (noutputs), d_input (ninputs), d_output (noutputs), - d_done (false) + d_done (false), + d_color (gr_block_detail::WHITE) { s_ncurrently_allocated++; } diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h index 8c4615919..d89b7fea1 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2004 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 2, 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 detail. - * + * * 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, @@ -75,18 +75,26 @@ class gr_block_detail { void produce_each (int how_many_items); + /*! + * \brief Allow the flowgraph to set for sorting and partitioning + */ + enum vcolor { WHITE, GREY, BLACK }; + void set_color(vcolor color) { d_color = color; } + vcolor color() const { return d_color; } + // ---------------------------------------------------------------------------- private: - unsigned int d_ninputs; - unsigned int d_noutputs; + unsigned int d_ninputs; + unsigned int d_noutputs; std::vector<gr_buffer_reader_sptr> d_input; - std::vector<gr_buffer_sptr> d_output; - bool d_done; - + std::vector<gr_buffer_sptr> d_output; + bool d_done; + vcolor d_color; + gr_block_detail (unsigned int ninputs, unsigned int noutputs); - friend gr_block_detail_sptr + friend gr_block_detail_sptr gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); }; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc new file mode 100644 index 000000000..65dea95fb --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_hier_block2.h> +#include <gr_io_signature.h> +#include <gr_hier_block2_detail.h> +#include <iostream> + +gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) +{ + return gr_hier_block2_sptr(new gr_hier_block2(name, input_signature, output_signature)); +} + +gr_hier_block2::gr_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : gr_basic_block(name, input_signature, output_signature), + d_detail(new gr_hier_block2_detail(this)) +{ +} + +gr_hier_block2::~gr_hier_block2() +{ + delete d_detail; +} + +void +gr_hier_block2::define_component(const std::string &name, gr_basic_block_sptr block) +{ + d_detail->define_component(name, block); +} + +void +gr_hier_block2::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + d_detail->connect(src_name, src_port, dst_name, dst_port); +} diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h new file mode 100644 index 000000000..9d2dd3569 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_GR_HIER_BLOCK2_H +#define INCLUDED_GR_HIER_BLOCK2_H + +#include <gr_basic_block.h> + +/*! + * \brief public constructor for gr_hier_block2 + */ +gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +class gr_hier_block2_detail; + +/*! + * \brief gr_hier_block2 - Hierarchical container class for gr_block's + * + */ +class gr_hier_block2 : public gr_basic_block +{ +private: + friend class gr_hier_block2_detail; + friend class gr_runtime_impl; + friend gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + /*! + * \brief Private implementation details of gr_hier_block2 + */ + gr_hier_block2_detail *d_detail; + +protected: + gr_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +public: + virtual ~gr_hier_block2(); + + void define_component(const std::string &name, gr_basic_block_sptr basic_block); + void connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port); +}; + +#endif /* INCLUDED_GR_HIER_BLOCK2_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i new file mode 100644 index 000000000..c5a676534 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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 2, 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. + */ + +%include <gr_basic_block.i> + +class gr_hier_block2; +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; +%template(gr_hier_block2_sptr) boost::shared_ptr<gr_hier_block2>; + +// Hack to have a Python shim implementation of gr.hier_block2 +// that instantiates one of these and passes through calls +%rename(hier_block2_swig) gr_make_hier_block2; +gr_hier_block2_sptr gr_make_hier_block2(const std::string name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +class gr_hier_block2 : public gr_basic_block +{ +private: + gr_hier_block2(const std::string name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +public: + ~gr_hier_block2 (); + + // Add a named block to the container + void define_component(const std::string &name, gr_basic_block_sptr basic_block) + throw (std::invalid_argument); + void connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) + throw (std::invalid_argument); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc new file mode 100644 index 000000000..545a64bfd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -0,0 +1,227 @@ +/* + * Copyright 2006 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 2, 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_hier_block2_detail.h> +#include <gr_simple_flowgraph.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) : +d_owner(owner) +{ +} + +gr_hier_block2_detail::~gr_hier_block2_detail() +{ + d_owner = 0; // Don't use delete, we didn't allocate +} + +gr_basic_block_sptr +gr_hier_block2_detail::lookup_block(const std::string &name) +{ + gr_hier_component_miter_t p = d_components.find(name); + if (p != d_components.end()) + return p->second; + else + return gr_basic_block_sptr(); +} + +void +gr_hier_block2_detail::define_component(const std::string &name, gr_basic_block_sptr block) +{ + if (!block) + throw std::invalid_argument("null block passed"); + + if (name == "self") + throw std::invalid_argument("name is reserved"); + + // TODO: reject names with '.' inside + + if (!lookup_block(name)) + d_components[name] = block; + else + throw std::invalid_argument("name already in use"); +} + +void +gr_hier_block2_detail::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + gr_io_signature_sptr src_io_signature; + gr_io_signature_sptr dst_io_signature; + + // Check against our *input_signature* if we're wiring from one of our external inputs + if (src_name == "self") + src_io_signature = d_owner->input_signature(); + else { + gr_basic_block_sptr src_block = lookup_block(src_name); + if (!src_block) + throw std::invalid_argument("undefined src name"); + src_io_signature = src_block->output_signature(); + } + + // Check against our *output_signature* if we're wiring to one of our external outputs + if (dst_name == "self") + dst_io_signature = d_owner->output_signature(); + else { + gr_basic_block_sptr dst_block = lookup_block(dst_name); + if (!dst_block) + throw std::invalid_argument("undefined dst name"); + dst_io_signature = dst_block->input_signature(); + } + + // Check port numbers are valid + check_valid_port(src_io_signature, src_port); + check_valid_port(dst_io_signature, dst_port); + + // Check destination port not already in use + check_dst_not_used(dst_name, dst_port); + + // Check endpoint types match + check_type_match(src_io_signature, src_port, dst_io_signature, dst_port); + + d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port)); +} + +void +gr_hier_block2_detail::check_valid_port(gr_io_signature_sptr sig, int port) +{ + if (port < 0) + throw std::invalid_argument("port number must not be negative"); + + if (sig->max_streams() >= 0 && port >= sig->max_streams()) + throw std::invalid_argument("port number exceeds max streams"); +} + +void +gr_hier_block2_detail::check_dst_not_used(const std::string name, int port) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->dst_name() == name && (*p)->dst_port() == port) + throw std::invalid_argument("destination port in use"); +} + +void +gr_hier_block2_detail::check_type_match(gr_io_signature_sptr src_sig, int src_port, + gr_io_signature_sptr dst_sig, int dst_port) +{ + if (src_sig->sizeof_stream_item(src_port) != dst_sig->sizeof_stream_item(dst_port)) + throw std::invalid_argument("type mismatch"); +} + +std::string +gr_hier_block2_detail::prepend_prefix(const std::string &prefix, const std::string &str) +{ + return prefix + ((prefix == "") ? "" : ".") + str; +} + +gr_endpoint +gr_hier_block2_detail::match_endpoint(const std::string &name, int port, bool is_input) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (is_input) { + if ((*p)->src_name() == name && (*p)->src_port() == port) + return resolve_endpoint((*p)->dst_name(), (*p)->dst_port(), "", !is_input); + } + else { + if ((*p)->dst_name() == name && (*p)->dst_port() == port) + return resolve_endpoint((*p)->src_name(), (*p)->src_port(), "", !is_input); + } + } + + // Should never get here + throw std::runtime_error("unable to match endpoint"); +} + +gr_endpoint +gr_hier_block2_detail::resolve_endpoint(const std::string &name, int port, + const std::string &prefix, bool is_input) +{ + gr_basic_block_sptr basic_block = lookup_block(name); + + // Check if 'name' points to gr_block (leaf node) + gr_block_sptr block(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(basic_block)); + if (block) + return gr_endpoint(prepend_prefix(prefix, name), port); + + // Check if 'name' points to hierarchical block + gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(basic_block)); + if (hier_block2) { + std::string child_prefix = prepend_prefix(prefix, name); + gr_endpoint match(hier_block2->d_detail->match_endpoint("self", port, !is_input)); + return gr_endpoint(prepend_prefix(child_prefix, match.name()), match.port()); + } + + // Shouldn't ever get here + throw std::runtime_error("unable to resolve endpoint"); +} + +void +gr_hier_block2_detail::flatten(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +{ + flatten_components(sfg, prefix); + flatten_edges(sfg, prefix); +} + +void +gr_hier_block2_detail::flatten_components(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +{ + // Add my non-hierarchical components to the simple flowgraph, then recurse + for (gr_hier_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + std::string name = prepend_prefix(prefix, p->first); + + gr_basic_block_sptr basic_block = p->second; + gr_block_sptr block(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(basic_block)); + if (block) + sfg->define_component(name, block); + + gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(basic_block)); + if (hier_block2) + hier_block2->d_detail->flatten_components(sfg, name); + } +} + +void +gr_hier_block2_detail::flatten_edges(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +{ + // Add my edges to the flow graph, resolving references to actual endpoints + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + // Connections to self get resolved/added by parent if actually connected + if ((*p)->src_name() == "self" || (*p)->dst_name() == "self") + continue; + + gr_endpoint src_endp = resolve_endpoint((*p)->src_name(), (*p)->src_port(), prefix, true); + gr_endpoint dst_endp = resolve_endpoint((*p)->dst_name(), (*p)->dst_port(), prefix, false); + sfg->connect(src_endp.name(), src_endp.port(), dst_endp.name(), dst_endp.port()); + } + + // Recurse hierarchical children + for (gr_hier_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(p->second)); + if (hier_block2) + hier_block2->d_detail->flatten_edges(sfg, prepend_prefix(prefix, p->first)); + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h new file mode 100644 index 000000000..095bd40f5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h @@ -0,0 +1,66 @@ +/* + * Copyright 2006 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 2, 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_GR_HIER_BLOCK2_DETAIL_H +#define INCLUDED_GR_HIER_BLOCK2_DETAIL_H + +#include <gr_hier_block2.h> +#include <gr_simple_flowgraph_detail.h> +#include <boost/utility.hpp> + +typedef std::map<std::string, gr_basic_block_sptr> gr_hier_component_map_t; +typedef std::map<std::string, gr_basic_block_sptr>::iterator gr_hier_component_miter_t; + +class gr_hier_block2_detail : boost::noncopyable +{ +private: + friend class gr_hier_block2; + friend class gr_runtime_impl; + + // Constructor--it's private, only friends can instantiate + gr_hier_block2_detail(gr_hier_block2 *owner); + + // Private implementation data + gr_hier_block2 *d_owner; + gr_hier_component_map_t d_components; + gr_edge_vector_t d_edges; + + // Private implementation methods + void define_component(const std::string &name, gr_basic_block_sptr block); + gr_basic_block_sptr lookup_block(const std::string &name); + void connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port); + void check_valid_port(gr_io_signature_sptr sig, int port); + void check_dst_not_used(const std::string name, int port); + void check_type_match(gr_io_signature_sptr src_sig, int src_port, + gr_io_signature_sptr dst_sig, int dst_port); + std::string prepend_prefix(const std::string &prefix, const std::string &str); + void flatten(gr_simple_flowgraph_sptr sfg, const std::string &prefix = ""); + void flatten_components(gr_simple_flowgraph_sptr sfg, const std::string &prefix); + void flatten_edges(gr_simple_flowgraph_sptr sfg, const std::string &prefix); + gr_endpoint match_endpoint(const std::string &name, int port, bool is_input); + gr_endpoint resolve_endpoint(const std::string &name, int port, + const std::string &prefix, bool is_input); + +public: + ~gr_hier_block2_detail(); +}; + +#endif /* INCLUDED_GR_HIER_BLOCK2_DETAIL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.cc b/gnuradio-core/src/lib/runtime/gr_runtime.cc new file mode 100644 index 000000000..926e87857 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_runtime.h> +#include <gr_runtime_impl.h> +#include <iostream> + +gr_runtime_sptr +gr_make_runtime(gr_hier_block2_sptr top_block) +{ + return gr_runtime_sptr(new gr_runtime(top_block)); +} + +gr_runtime::gr_runtime(gr_hier_block2_sptr top_block) +{ + d_impl = new gr_runtime_impl(top_block); +} + +gr_runtime::~gr_runtime() +{ + delete d_impl; +} + +void +gr_runtime::start() +{ + d_impl->start(); +} + +void +gr_runtime::stop() +{ + d_impl->stop(); +} + +void +gr_runtime::wait() +{ + d_impl->wait(); +} + +void +gr_runtime::run() +{ + start(); + wait(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.h b/gnuradio-core/src/lib/runtime/gr_runtime.h new file mode 100644 index 000000000..fc58da456 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_GR_RUNTIME_H +#define INCLUDED_GR_RUNTIME_H + +#include <gr_runtime_types.h> + +class gr_runtime_impl; + +gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block); + +class gr_runtime +{ +private: + gr_runtime(gr_hier_block2_sptr top_block); + friend gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block); + + gr_runtime_impl *d_impl; + +public: + ~gr_runtime(); + + void start(); + void stop(); + void wait(); + void run(); +}; + +#endif /* INCLUDED_GR_RUNTIME_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.i b/gnuradio-core/src/lib/runtime/gr_runtime.i new file mode 100644 index 000000000..496adff37 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 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 2, 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. + */ + +class gr_runtime; +typedef boost::shared_ptr<gr_runtime> gr_runtime_sptr; +%template(gr_runtime_sptr) boost::shared_ptr<gr_runtime>; + +%rename(runtime) gr_make_runtime; +gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block); + +class gr_runtime +{ +protected: + gr_runtime(gr_hier_block2_sptr top_block); + +public: + void start() + throw (std::runtime_error); + void stop(); + void wait(); + void run() + throw (std::runtime_error); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc new file mode 100644 index 000000000..2b104cd99 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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 + +#define GR_RUNTIME_IMPL_DEBUG 0 + +#include <gr_runtime_impl.h> +#include <gr_simple_flowgraph.h> +#include <gr_hier_block2.h> +#include <gr_hier_block2_detail.h> +#include <stdexcept> +#include <iostream> + +gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) : +d_running(false), +d_top_block(top_block), +d_sfg(gr_make_simple_flowgraph()), +d_graphs() +{ +} + +gr_runtime_impl::~gr_runtime_impl() +{ +} + +void +gr_runtime_impl::start() +{ + if (d_running) + throw std::runtime_error("already running"); + else + d_running = true; + + d_sfg->d_detail->reset(); + d_top_block->d_detail->flatten(d_sfg); + d_sfg->d_detail->validate(); + d_sfg->d_detail->setup_connections(); + + d_graphs = d_sfg->d_detail->partition(); + if (GR_RUNTIME_IMPL_DEBUG) + std::cout << "Flow graph has " << d_graphs.size() + << " sub-graphs." << std::endl; + + d_threads.clear(); + for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin(); + p != d_graphs.end(); p++) { + gr_scheduler_thread_sptr thread = gr_make_scheduler_thread(*p); + thread->start(); + d_threads.push_back(thread); + } +} + +void +gr_runtime_impl::stop() +{ + if (!d_running) + return; + + for (gr_scheduler_thread_viter_t p = d_threads.begin(); + p != d_threads.end(); p++) + (*p)->stop(); + + d_running = false; +} + +void +gr_runtime_impl::wait() +{ + for (gr_scheduler_thread_viter_t p = d_threads.begin(); + p != d_threads.end(); p++) { + while(1) { + (*p)->join(NULL); + if (!(*p)->state() == omni_thread::STATE_TERMINATED) + break; + } + } +} + +gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph) +{ + return gr_scheduler_thread_sptr(new gr_scheduler_thread(graph)); +} + +gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) : + omni_thread(NULL, PRIORITY_NORMAL), + d_sts(gr_make_single_threaded_scheduler(graph)) +{ +} + +gr_scheduler_thread::~gr_scheduler_thread() +{ +} + +void gr_scheduler_thread::start() +{ + start_undetached(); +} + +void *gr_scheduler_thread::run_undetached(void *arg) +{ + d_sts->run(); + return 0; +} + +void gr_scheduler_thread::stop() +{ + d_sts->stop(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h new file mode 100644 index 000000000..54977ef97 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_GR_RUNTIME_IMPL_H +#define INCLUDED_GR_RUNTIME_IMPL_H + +#include <gr_runtime_types.h> +#include <gr_block.h> +#include <omnithread.h> +#include <gr_single_threaded_scheduler.h> + +class gr_scheduler_thread; +typedef boost::shared_ptr<gr_scheduler_thread> gr_scheduler_thread_sptr; +typedef std::vector<gr_scheduler_thread_sptr> gr_scheduler_thread_vector_t; +typedef std::vector<gr_scheduler_thread_sptr>::iterator gr_scheduler_thread_viter_t; + +gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph); + +class gr_scheduler_thread : public omni_thread +{ +private: + gr_scheduler_thread(gr_block_vector_t graph); + friend gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph); + + gr_single_threaded_scheduler_sptr d_sts; + +public: + ~gr_scheduler_thread(); + virtual void *run_undetached(void *arg); + void start(); + void stop(); +}; + +class gr_runtime_impl +{ +private: + gr_runtime_impl(gr_hier_block2_sptr top_block); + friend class gr_runtime; + + bool d_running; + gr_hier_block2_sptr d_top_block; + gr_simple_flowgraph_sptr d_sfg; + std::vector<gr_block_vector_t> d_graphs; + gr_scheduler_thread_vector_t d_threads; + + void start(); + void stop(); + void wait(); + +public: + ~gr_runtime_impl(); + +}; + +#endif /* INCLUDED_GR_RUNTIME_IMPL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_types.h b/gnuradio-core/src/lib/runtime/gr_runtime_types.h index 55cbabe18..dfa0ce94f 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime_types.h +++ b/gnuradio-core/src/lib/runtime/gr_runtime_types.h @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_RUNTIME_H -#define INCLUDED_GR_RUNTIME_H +#ifndef INCLUDED_GR_RUNTIME_TYPES_H +#define INCLUDED_GR_RUNTIME_TYPES_H #include <gr_types.h> @@ -29,16 +29,24 @@ * typedefs for smart pointers we use throughout the runtime system */ +class gr_basic_block; class gr_block; class gr_block_detail; +class gr_hier_block2; class gr_io_signature; class gr_buffer; class gr_buffer_reader; +class gr_simple_flowgraph; +class gr_runtime; -typedef boost::shared_ptr<gr_block> gr_block_sptr; -typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; -typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; -typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; -typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; +typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; +typedef boost::shared_ptr<gr_block> gr_block_sptr; +typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; +typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; +typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; +typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; +typedef boost::shared_ptr<gr_runtime> gr_runtime_sptr; +typedef boost::shared_ptr<gr_simple_flowgraph> gr_simple_flowgraph_sptr; -#endif /* INCLUDED_GR_RUNTIME_H */ +#endif /* INCLUDED_GR_RUNTIME_TYPES_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc new file mode 100644 index 000000000..21aeb587c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_simple_flowgraph.h> +#include <gr_simple_flowgraph_detail.h> +#include <iostream> + +#define GR_SIMPLE_FLOWGRAPH_DEBUG 0 + +gr_simple_flowgraph_sptr gr_make_simple_flowgraph() +{ + return gr_simple_flowgraph_sptr(new gr_simple_flowgraph()); +} + +gr_simple_flowgraph::gr_simple_flowgraph() : +d_detail(new gr_simple_flowgraph_detail()) +{ +} + +gr_simple_flowgraph::~gr_simple_flowgraph() +{ + delete d_detail; +} + +void +gr_simple_flowgraph::define_component(const std::string &name, gr_block_sptr block) +{ + if (GR_SIMPLE_FLOWGRAPH_DEBUG) + std::cout << "Defining block " << block << " as " << name << std::endl; + d_detail->define_component(name, block); +} + +void +gr_simple_flowgraph::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + d_detail->connect(src_name, src_port, dst_name, dst_port); +} + +void +gr_simple_flowgraph::validate() +{ + d_detail->validate(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h new file mode 100644 index 000000000..ca2c505e5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_GR_SIMPLE_FLOWGRAPH_H +#define INCLUDED_GR_SIMPLE_FLOWGRAPH_H + +#include <gr_block.h> +#include <boost/shared_ptr.hpp> +#include <string> + +gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); + +class gr_simple_flowgraph_detail; + +class gr_simple_flowgraph +{ +private: + friend class gr_runtime_impl; + friend gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); + gr_simple_flowgraph(); + + gr_simple_flowgraph_detail *d_detail; + +public: + ~gr_simple_flowgraph(); + + void define_component(const std::string &name, gr_block_sptr block); + void connect(const std::string &src, int src_port, + const std::string &dst, int dst_port); + void validate(); +}; + +#endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i new file mode 100644 index 000000000..c3654fe50 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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. + */ + +class gr_simple_flowgraph; +typedef boost::shared_ptr<gr_simple_flowgraph> gr_simple_flowgraph_sptr; +%template(gr_simple_flowgraph_sptr) boost::shared_ptr<gr_simple_flowgraph>; +%rename(simple_flowgraph) gr_make_simple_flowgraph; +%ignore gr_simple_flowgraph; + +gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); + +class gr_simple_flowgraph +{ +private: + gr_simple_flowgraph(); + +public: + ~gr_simple_flowgraph(); + void define_component(const std::string name, gr_block_sptr block) + throw (std::invalid_argument); + void connect(const std::string &src, int src_port, + const std::string &dst, int dst_port) + throw (std::invalid_argument); + void validate() + throw (std::runtime_error); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc new file mode 100644 index 000000000..2698bc6d8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc @@ -0,0 +1,471 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_simple_flowgraph.h> +#include <gr_simple_flowgraph_detail.h> +#include <gr_io_signature.h> +#include <gr_block_detail.h> +#include <gr_buffer.h> +#include <iostream> +#include <stdexcept> + +#define GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG 0 + +gr_edge_sptr +gr_make_edge(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + return gr_edge_sptr(new gr_edge(src_name, src_port, dst_name, dst_port)); +} + +gr_edge::gr_edge(const std::string &src_name, int src_port, const std::string &dst_name, int dst_port) + : d_src(src_name, src_port), + d_dst(dst_name, dst_port) +{ +} + +gr_edge::~gr_edge() +{ +} + +gr_simple_flowgraph_detail::gr_simple_flowgraph_detail() : +d_components(), +d_edges() +{ +} + +gr_simple_flowgraph_detail::~gr_simple_flowgraph_detail() +{ +} + +void +gr_simple_flowgraph_detail::reset() +{ + // Boost shared pointers will deallocate as needed + d_edges.clear(); + d_components.clear(); +} + +gr_block_sptr +gr_simple_flowgraph_detail::lookup_block(const std::string &name) +{ + gr_component_miter_t p = d_components.find(name); + if (p != d_components.end()) + return p->second; + else + return gr_block_sptr(); +} + +void +gr_simple_flowgraph_detail::define_component(const std::string &name, gr_block_sptr block) +{ + if (!block) + throw std::invalid_argument("null block passed"); + + if (!lookup_block(name)) + d_components[name] = block; + else + throw std::invalid_argument("name already in use"); +} + +void +gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + gr_block_sptr src_block = lookup_block(src_name); + gr_block_sptr dst_block = lookup_block(dst_name); + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Connecting " << src_name << ":" << src_port << "->" + << dst_name << ":" << dst_port << std::endl; + + if (!src_block) + throw std::invalid_argument("unknown src name"); + if (!dst_block) + throw std::invalid_argument("unknown dst name"); + + check_valid_port(src_block->output_signature(), src_port); + check_valid_port(dst_block->input_signature(), dst_port); + check_dst_not_used(dst_name, dst_port); + check_type_match(src_block, src_port, dst_block, dst_port); + + d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port)); +} + +void +gr_simple_flowgraph_detail::check_valid_port(gr_io_signature_sptr sig, int port) +{ + if (port < 0) + throw std::invalid_argument("negative port number"); + if (sig->max_streams() >= 0 && port >= sig->max_streams()) + throw std::invalid_argument("port number exceeds max"); +} + +void +gr_simple_flowgraph_detail::check_dst_not_used(const std::string &name, int port) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->dst_name() == name && (*p)->dst_port() == port) + throw std::invalid_argument("dst already in use"); +} + +void +gr_simple_flowgraph_detail::check_type_match(gr_block_sptr src_block, int src_port, + gr_block_sptr dst_block, int dst_port) +{ + int src_size = src_block->output_signature()->sizeof_stream_item(src_port); + int dst_size = dst_block->input_signature()->sizeof_stream_item(dst_port); + + if (src_size != dst_size) + throw std::invalid_argument("type size mismatch"); +} + +void +gr_simple_flowgraph_detail::validate() +{ + for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + std::vector<int> used_ports; + int ninputs, noutputs; + + used_ports = calc_used_ports(p->first, true); // inputs + ninputs = used_ports.size(); + check_contiguity(p->second, used_ports, true); // inputs + + used_ports = calc_used_ports(p->first, false); // outputs + noutputs = used_ports.size(); + check_contiguity(p->second, used_ports, false); // outputs + + if (!(p->second->check_topology(ninputs, noutputs))) + throw std::runtime_error("check topology failed"); + } +} + +std::vector<int> +gr_simple_flowgraph_detail::calc_used_ports(const std::string &name, bool check_inputs) +{ + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Calculating used " << (check_inputs ? "input " : "output ") + << "ports..."; + + std::vector<int> tmp, result; + std::insert_iterator<std::vector<int> > inserter(result, result.begin()); + + gr_edge_vector_t edges = calc_connections(name, check_inputs); + + for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) { + if (check_inputs == true) + tmp.push_back((*p)->dst_port()); + else + tmp.push_back((*p)->src_port()); + } + + // remove duplicates + std::sort(tmp.begin(), tmp.end()); + std::unique_copy(tmp.begin(), tmp.end(), inserter); + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << result.size() << std::endl; + + return result; +} + +gr_edge_vector_t +gr_simple_flowgraph_detail::calc_connections(const std::string &name, bool check_inputs) +{ + gr_edge_vector_t result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (check_inputs) { + if ((*p)->dst_name() == name) + result.push_back(*p); + } + else { + if ((*p)->src_name() == name) + result.push_back(*p); + } + } + + return result; // assumes no duplicates +} + +void +gr_simple_flowgraph_detail::check_contiguity(gr_block_sptr block, + const std::vector<int> &used_ports, + bool check_inputs) +{ + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Checking " << (check_inputs ? "input " : "output ") + << "contiguity..."; + + gr_io_signature_sptr sig = + check_inputs ? block->input_signature() : block->output_signature(); + + int nports = used_ports.size(); + int min_ports = sig->min_streams(); + + if (nports == 0) { + if (min_ports == 0) { + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "ok." << std::endl; + return; + } + else { + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "needs " << min_ports << ", only has " + << nports << std::endl; + + throw std::runtime_error("insufficient ports"); + } + } + + if (used_ports[nports-1]+1 != nports) { + for (int i = 0; i < nports; i++) { + if (used_ports[i] != i) { + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "missing " << (check_inputs ? "input ":"output ") + << i << std::endl; + + throw std::runtime_error("missing input assignment"); + } + } + } + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "ok." << std::endl; +} + +void +gr_simple_flowgraph_detail::setup_connections() +{ + // Assign block details to component blocks + for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Allocating output buffers for " << p->first << "..." << std::endl; + + int ninputs = calc_used_ports(p->first, true).size(); + int noutputs = calc_used_ports(p->first, false).size(); + gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs); + for (int i = 0; i < noutputs; i++) + detail->set_output(i, allocate_buffer(p->first, i)); + p->second->set_detail(detail); + } + + // Connect inputs to outputs for each block + for(gr_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + // Get its detail and edges that feed into it + gr_block_detail_sptr detail = p->second->detail(); + gr_edge_vector_t in_edges = calc_upstream_edges(p->first); + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + if (in_edges.size() > 0) + std::cout << "Connecting inputs to " << p->first << "..." << std::endl; + + // For each edge that feeds into it + for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) { + // Set the input buffer on the destination port to the output + // buffer on the source port + int dst_port = (*e)->dst_port(); + int src_port = (*e)->src_port(); + gr_block_sptr src_block = lookup_block((*e)->src_name()); + gr_buffer_sptr src_buffer = src_block->detail()->output(src_port); + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Setting input on " << (*e)->dst_name() + << ":" << dst_port << std::endl; + + detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, p->second->history()-1)); + } + } +} + +gr_buffer_sptr +gr_simple_flowgraph_detail::allocate_buffer(const std::string &name, int port) +{ + gr_block_sptr block = lookup_block(name); + int item_size = block->output_signature()->sizeof_stream_item(port); + int nitems = s_fixed_buffer_size/item_size; + + // Make sure there are at least twice the output_multiple no. of items + if (nitems < 2*block->output_multiple()) // Note: this means output_multiple() + nitems = 2*block->output_multiple(); // can't be changed by block dynamically + + // If any downstream blocks are decimators and/or have a large output_multiple, + // ensure we have a buffer at least twice their decimation factor*output_multiple + gr_block_vector_t blocks = calc_downstream_blocks(name, port); + for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + int decimation = (int)(1.0/(*p)->relative_rate()); + int multiple = (*p)->output_multiple(); + int history = (*p)->history(); + nitems = std::max(nitems, 2*(decimation*multiple+history)); + } + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Allocating buffer for port " << port << " with " + << nitems << " items of size " << item_size << std::endl; + + return gr_make_buffer(nitems, item_size); +} + +gr_block_vector_t +gr_simple_flowgraph_detail::calc_downstream_blocks(const std::string &name, int port) +{ + gr_block_vector_t tmp, result; + std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->src_name() == name && (*p)->src_port() == port) + tmp.push_back(lookup_block((*p)->dst_name())); + + // Remove duplicates + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_edge_vector_t +gr_simple_flowgraph_detail::calc_upstream_edges(const std::string &name) +{ + gr_edge_vector_t result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->dst_name() == name) + result.push_back(*p); + + return result; // Assume no duplicates +} + +gr_block_vector_t +gr_simple_flowgraph_detail::calc_used_blocks() +{ + std::vector<std::string> tmp, tmp_unique; + std::insert_iterator<std::vector<std::string> > inserter(tmp_unique, tmp_unique.begin()); + gr_block_vector_t result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + tmp.push_back((*p)->src_name()); + tmp.push_back((*p)->dst_name()); + } + + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + + for (std::vector<std::string>::iterator p = tmp_unique.begin(); + p != tmp_unique.end(); p++) + result.push_back(lookup_block(*p)); + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Flowgraph uses " << result.size() + << " distinct blocks." << std::endl; + + return result; +} + +std::vector<gr_block_vector_t> +gr_simple_flowgraph_detail::partition() +{ + std::vector<gr_block_vector_t> result; + gr_block_vector_t blocks = calc_used_blocks(); + gr_block_vector_t graph; + + while (blocks.size() > 0) { + graph = calc_reachable_blocks(blocks[0], blocks); + assert(graph.size()); + result.push_back(topological_sort(graph)); + + for (gr_block_viter_t p = graph.begin(); p != graph.end(); p++) + blocks.erase(find(blocks.begin(), blocks.end(), *p)); + } + + return result; +} + +gr_block_vector_t +gr_simple_flowgraph_detail::calc_reachable_blocks(gr_block_sptr block, gr_block_vector_t &blocks) +{ + gr_block_vector_t result; + + // Mark all blocks as unvisited + for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + (*p)->detail()->set_color(gr_block_detail::WHITE); + + // Recursively mark all reachable blocks + reachable_dfs_visit(block, blocks); + + // Collect all the blocks that have been visited + for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + if ((*p)->detail()->color() == gr_block_detail::BLACK) + result.push_back(*p); + + return result; +} + +// Recursively mark all reachable blocks from given block and block list +void +gr_simple_flowgraph_detail::reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks) +{ + // Mark the current one as visited + block->detail()->set_color(gr_block_detail::BLACK); + + // Recurse into adjacent vertices + gr_block_vector_t adjacent = calc_adjacent_blocks(block, blocks); + + for (gr_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) + if ((*p)->detail()->color() == gr_block_detail::WHITE) + reachable_dfs_visit(*p, blocks); +} + +// Return a list of block adjacent to a given block along any edge +gr_block_vector_t +gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_block_sptr block, gr_block_vector_t &blocks) +{ + gr_block_vector_t tmp, result; + std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + + // Find any blocks that are inputs or outputs + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (lookup_block((*p)->src_name()) == block) + tmp.push_back(lookup_block((*p)->dst_name())); + if (lookup_block((*p)->dst_name()) == block) + tmp.push_back(lookup_block((*p)->src_name())); + } + + // Remove duplicates + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_block_vector_t +gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks) +{ + gr_block_vector_t result; + + // NOP for now + result = blocks; + + return result; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h new file mode 100644 index 000000000..368a0619f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h @@ -0,0 +1,128 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_GR_SIMPLE_FLOWGRAPH_DETAIL_H +#define INCLUDED_GR_SIMPLE_FLOWGRAPH_DETAIL_H + +#include <gr_block.h> +#include <map> + +#define GR_FIXED_BUFFER_SIZE (32*(1L<<10)) + +typedef std::map<std::string, gr_block_sptr> gr_component_map_t; +typedef std::map<std::string, gr_block_sptr>::iterator gr_component_miter_t; + +class gr_endpoint +{ +private: + std::string d_name; + int d_port; + +public: + gr_endpoint(const std::string &name, int port) { d_name = name; d_port = port; } + const std::string &name() const { return d_name; } + int port() const { return d_port; } +}; + +class gr_edge; +typedef boost::shared_ptr<gr_edge> gr_edge_sptr; +gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port); + +class gr_edge +{ +private: + friend gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port); + gr_edge(const std::string &name, int src_port, + const std::string &name, int dst_port); + + gr_endpoint d_src; + gr_endpoint d_dst; + +public: + ~gr_edge(); + const std::string src_name() const { return d_src.name(); } + const std::string dst_name() const { return d_dst.name(); } + int src_port() const { return d_src.port(); } + int dst_port() const { return d_dst.port(); } +}; + +typedef std::vector<gr_edge_sptr> gr_edge_vector_t; +typedef std::vector<gr_edge_sptr>::iterator gr_edge_viter_t; + +class gr_simple_flowgraph_detail +{ +private: + friend class gr_simple_flowgraph; + friend class gr_runtime_impl; + + gr_simple_flowgraph_detail(); + + gr_component_map_t d_components; + gr_edge_vector_t d_edges; + static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE; + + void reset(); + void define_component(const std::string &name, gr_block_sptr block); + void connect(const std::string &src, int src_port, + const std::string &dst, int dst_port); + gr_block_sptr lookup_block(const std::string &name); + void check_valid_port(gr_io_signature_sptr sig, int port); + void check_dst_not_used(const std::string &name, int port); + void check_type_match(gr_block_sptr src_block, int src_port, + gr_block_sptr dst_block, int dst_port); + void validate(); + gr_edge_vector_t calc_connections(const std::string &name, bool check_inputs); // false=use outputs + std::vector<int> calc_used_ports(const std::string &name, bool check_inputs); + void check_contiguity(gr_block_sptr block, const std::vector<int> &used_ports, + bool check_inputs); + void setup_connections(); + gr_buffer_sptr allocate_buffer(const std::string &name, int port); + gr_block_vector_t calc_downstream_blocks(const std::string &name, int port); + gr_edge_vector_t calc_upstream_edges(const std::string &name); + gr_block_vector_t calc_used_blocks(); + std::vector<gr_block_vector_t> partition(); + gr_block_vector_t calc_reachable_blocks(gr_block_sptr block, gr_block_vector_t &blocks); + gr_block_vector_t topological_sort(gr_block_vector_t &blocks); + void reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks); + gr_block_vector_t calc_adjacent_blocks(gr_block_sptr block, gr_block_vector_t &blocks); + +public: + ~gr_simple_flowgraph_detail(); +}; + +inline std::ostream& +operator <<(std::ostream& os, const gr_block_sptr p) +{ + os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>"; + return os; +} + +inline std::ostream& +operator <<(std::ostream &os, const gr_endpoint endp) +{ + os << endp.name() << ":" << endp.port(); + return os; +} + +#endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_block.cc index 4773a6eaa..630d72749 100644 --- a/gnuradio-core/src/lib/runtime/qa_gr_block.cc +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.cc @@ -25,7 +25,6 @@ #endif #include <qa_gr_block.h> #include <gr_block.h> -#include <gr_runtime_types.h> #include <gr_io_signature.h> #include <gr_null_sink.h> #include <gr_null_source.h> diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc new file mode 100644 index 000000000..766ea2f6b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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 <qa_gr_hier_block2.h> +#include <gr_hier_block2.h> +#include <gr_io_signature.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> + +void qa_gr_hier_block2::test_make() +{ + gr_hier_block2_sptr src1(gr_make_hier_block2("test", + gr_make_io_signature(1, 1, sizeof(int)), + gr_make_io_signature(1, 1, sizeof(int)))); + + CPPUNIT_ASSERT(src1); + CPPUNIT_ASSERT_EQUAL(std::string("test"), src1->name()); + CPPUNIT_ASSERT_EQUAL(1, src1->input_signature()->max_streams()); + CPPUNIT_ASSERT_EQUAL(1, src1->output_signature()->min_streams()); + CPPUNIT_ASSERT_EQUAL(1, src1->output_signature()->max_streams()); + CPPUNIT_ASSERT_EQUAL(sizeof(int), + src1->output_signature()->sizeof_stream_item(0)); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h new file mode 100644 index 000000000..a6bd8d97b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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_QA_GR_HIER_BLOCK2_H +#define INCLUDED_QA_GR_HIER_BLOCK2_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_hier_block2 : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_gr_hier_block2); + + CPPUNIT_TEST(test_make); + + CPPUNIT_TEST_SUITE_END(); + +private: + void test_make(); + void test_derived(); +}; + +#endif /* INCLUDED_QA_GR_HIER_BLOCK2_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc index 165a34703..ca0c71d3c 100644 --- a/gnuradio-core/src/lib/runtime/qa_runtime.cc +++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc @@ -33,6 +33,7 @@ #include <qa_gr_vmcircbuf.h> #include <qa_gr_io_signature.h> #include <qa_gr_block.h> +#include <qa_gr_hier_block2.h> #include <qa_gr_buffer.h> CppUnit::TestSuite * @@ -43,6 +44,7 @@ qa_runtime::suite () s->addTest (qa_gr_vmcircbuf::suite ()); s->addTest (qa_gr_io_signature::suite ()); s->addTest (qa_gr_block::suite ()); + s->addTest (qa_gr_hier_block2::suite ()); s->addTest (qa_gr_buffer::suite ()); return s; diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i index f2fd36437..8e6c01f9a 100644 --- a/gnuradio-core/src/lib/runtime/runtime.i +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -26,6 +26,9 @@ #include <gr_buffer.h> #include <gr_block.h> #include <gr_block_detail.h> +#include <gr_hier_block2.h> +#include <gr_runtime.h> +#include <gr_simple_flowgraph.h> #include <gr_single_threaded_scheduler.h> #include <gr_message.h> #include <gr_msg_handler.h> @@ -37,9 +40,12 @@ %include <gr_io_signature.i> %include <gr_buffer.i> +%include <gr_basic_block.i> %include <gr_block.i> %include <gr_block_detail.i> +%include <gr_hier_block2.i> %include <gr_swig_block_magic.i> +%include <gr_simple_flowgraph.i> %include <gr_single_threaded_scheduler.i> %include <gr_message.i> %include <gr_msg_handler.i> @@ -47,3 +53,4 @@ %include <gr_dispatcher.i> %include <gr_error_handler.i> %include <gr_realtime.i> +%include <gr_runtime.i> diff --git a/gnuradio-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am index fcf026146..6400b842f 100644 --- a/gnuradio-core/src/python/gnuradio/gr/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am @@ -39,6 +39,7 @@ grgrpython_PYTHON = \ gr_threading_23.py \ gr_threading_24.py \ hier_block.py \ + hier_block2.py \ prefs.py \ scheduler.py @@ -63,6 +64,7 @@ noinst_PYTHON = \ qa_fsk_stuff.py \ qa_goertzel.py \ qa_head.py \ + qa_hier_block2.py \ qa_hilbert.py \ qa_iir.py \ qa_interleave.py \ diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py index 8adf7e308..d38804870 100644 --- a/gnuradio-core/src/python/gnuradio/gr/__init__.py +++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py @@ -29,7 +29,7 @@ from basic_flow_graph import * from flow_graph import * from exceptions import * from hier_block import * - +from hier_block2 import * # create a couple of aliases serial_to_parallel = stream_to_vector diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py new file mode 100644 index 000000000..c44e6f071 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py @@ -0,0 +1,40 @@ +# +# Copyright 2006 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 2, 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_swig_python import hier_block2_swig + +# +# This hack forces a 'has-a' relationship to look like an 'is-a' one. +# +# It allows Python classes to subclass this one, while passing through +# method calls to the C++ class shared pointer from SWIG. +# +# It also allows us to intercept method calls if needed +# +class hier_block2(object): + def __init__(self, name, input_signature, output_signature): + self._hb = hier_block2_swig(name, input_signature, output_signature) + + def __getattr__(self, name): + return getattr(self._hb, name) + + def define_component(self, name, comp): + return self._hb.define_component(name, comp.basic_block()) diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py new file mode 100755 index 000000000..9253b892a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + +class test_hier_block2(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_001_make(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + self.assertEqual("test_block", hblock.name()) + self.assertEqual(1, hblock.input_signature().max_streams()) + self.assertEqual(1, hblock.output_signature().min_streams()) + self.assertEqual(1, hblock.output_signature().max_streams()) + self.assertEqual(gr.sizeof_int, hblock.output_signature().sizeof_stream_item(0)) + + def test_002_define_component(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("src", gr.null_source(gr.sizeof_int)) + hblock.define_component("dst", gr.null_sink(gr.sizeof_int)) + + def test_003_define_component_reserved_input(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.define_component("self", gr.nop(gr.sizeof_int))) + + def test_004_define_component_name_in_use(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("src", gr.null_source(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.define_component("src", gr.null_sink(gr.sizeof_int))) + + def test_006_connect_internal(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.define_component("nop2", gr.nop(gr.sizeof_int)) + hblock.connect("nop1", 0, "nop2", 0) + + def test_007_connect_input(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.connect("self", 0, "nop1", 0) + + def test_008_connect_output(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.connect("nop1", 0, "self", 0) + + def test_009_connect_unknown_src(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.define_component("nop1", nop1) + self.assertRaises(ValueError, + lambda: hblock.connect("nop2", 0, "self", 0)) + + def test_010_connect_unknown_dst(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.connect("self", 0, "nop2", 0)) + + def test_011_connect_invalid_src_port_neg(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.connect("self", -1, "nop1", 0)) + + def test_012_connect_invalid_src_port_exceeds(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.connect("self", 1, "nop1", 0)) + + def test_013_connect_invalid_dst_port_neg(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.connect("self", -1, "nop1", 0)) + + def test_014_connect_invalid_dst_port_exceeds(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: hblock.connect("self", 1, "nop1", 0)) + + def test_015_connect_dst_port_in_use(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.define_component("nop1", nop1) + hblock.connect("nop1", 0, "self", 0); + self.assertRaises(ValueError, + lambda: hblock.connect("nop1", 0, "self", 0)) + + def test_016_connect_one_src_two_dst(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("src", gr.null_source(gr.sizeof_int)) + hblock.define_component("dst1", gr.null_sink(gr.sizeof_int)) + hblock.define_component("dst2", gr.null_sink(gr.sizeof_int)) + hblock.connect("src", 0, "dst1", 0) + hblock.connect("src", 0, "dst2", 0) + + def test_017_connect_type_mismatch(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_char)) + self.assertRaises(ValueError, + lambda: hblock.connect("nop1", 0, "self", 0)) + + def test_018_check_topology(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + hblock.check_topology(0, 0); + """ + def test_019_validate(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + runtime = gr.runtime(hblock) + runtime.validate() + + def test_020_validate_1(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + hblock.define_component("src", gr.null_source(gr.sizeof_int)) + hblock.define_component("dst1", gr.null_sink(gr.sizeof_int)) + hblock.define_component("dst2", gr.null_sink(gr.sizeof_int)) + hblock.connect("src", 0, "dst1", 0) + hblock.connect("src", 0, "dst2", 0) + runtime = gr.runtime(hblock) + runtime.validate() + + def test_021_validate_2(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + hblock.define_component("src1", gr.null_source(gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.define_component("dst1", gr.null_sink(gr.sizeof_int)) + hblock.define_component("dst2", gr.null_sink(gr.sizeof_int)) + hblock.connect("src1", 0, "nop1", 0) + hblock.connect("src1", 0, "nop1", 1) + hblock.connect("nop1", 0, "dst1", 0) + hblock.connect("nop1", 1, "dst2", 0) + runtime = gr.runtime(hblock) + runtime.validate() + + def test_022_validate_3(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + hblock.define_component("src1", gr.null_source(gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.define_component("dst1", gr.null_sink(gr.sizeof_int)) + hblock.define_component("dst2", gr.null_sink(gr.sizeof_int)) + hblock.connect("src1", 0, "nop1", 0) + hblock.connect("src1", 0, "nop1", 2) + hblock.connect("nop1", 0, "dst1", 0) + hblock.connect("nop1", 1, "dst2", 0) + runtime = gr.runtime(hblock) + self.assertRaises(RuntimeError, + lambda: runtime.validate()) + + def test_023_validate_4(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + hblock.define_component("src1", gr.null_source(gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.define_component("dst1", gr.null_sink(gr.sizeof_int)) + hblock.define_component("dst2", gr.null_sink(gr.sizeof_int)) + hblock.connect("src1", 0, "nop1", 0) + hblock.connect("src1", 0, "nop1", 1) + hblock.connect("nop1", 0, "dst1", 0) + hblock.connect("nop1", 2, "dst2", 0) + runtime = gr.runtime(hblock) + self.assertRaises(RuntimeError, + lambda: runtime.validate()) + + def test_024_validate_5(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,gr.sizeof_int), + gr.io_signature(0,0,gr.sizeof_int)) + hblock.define_component("src1", gr.null_source(gr.sizeof_int)) + hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + hblock.define_component("dst1", gr.null_sink(gr.sizeof_int)) + hblock.define_component("dst2", gr.null_sink(gr.sizeof_int)) + hblock.connect("src1", 0, "nop1", 0) + hblock.connect("src1", 0, "nop1", 1) + hblock.connect("nop1", 0, "dst1", 0) + hblock.connect("nop1", 1, "dst2", 0) + runtime = gr.runtime(hblock) + runtime.validate() + # Pending implementation of disconnect + # hblock.disconnect("src1", 0, "nop1", 1) + # runtime.validate() + # self.assertRaises(ValueError, + # lambda: hblock.disconnect("src1", 0, "nop1", 1)) + """ + +if __name__ == "__main__": + gr_unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_runtime.py b/gnuradio-core/src/python/gnuradio/gr/qa_runtime.py new file mode 100755 index 000000000..3e7f4e5f9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_runtime.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + +class test_runtime(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + """ + def test_001_run(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,0), + gr.io_signature(0,0,0)) + runtime = gr.runtime(hblock) + runtime.run() + + def test_002_run_twice(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(0,0,0), + gr.io_signature(0,0,0)) + runtime = gr.runtime(hblock) + runtime.run() + self.assertRaises(RuntimeError, lambda: runtime.run()) + """ + +if __name__ == "__main__": + gr_unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_simple_flowgraph.py b/gnuradio-core/src/python/gnuradio/gr/qa_simple_flowgraph.py new file mode 100755 index 000000000..939f5855f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_simple_flowgraph.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + +class test_simple_flowgraph(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_001_define_component(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + + def test_002_define_component_name_in_use(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.define_component("src", gr.null_sink(gr.sizeof_int))) + + def test_003_connect(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + sfg.connect("src", 0, "dst", 0) + + def test_004connect_unknown_src(self): + sfg = gr.simple_flowgraph() + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", 0, "dst", 0)) + + def test_005_connect_unknown_dst(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", 0, "dst", 0)) + + def test_006_connect_invalid_src_port_neg(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", -1, "dst", 0)) + + def test_007_connect_invalid_src_port_exceeds(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", 1, "dst", 0)) + + def test_008_connect_invalid_dst_port_neg(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", 0, "dst", -1)) + + def test_009_connect_invalid_dst_port_exceeds(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", 0, "dst", 1)) + + def test_010_connect_invalid_dst_port_in_use(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src1", gr.null_source(gr.sizeof_int)) + sfg.define_component("src2", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) + sfg.connect("src1", 0, "dst", 0) + self.assertRaises(ValueError, + lambda: sfg.connect("src2", 0, "dst", 0)) + + def test_011_connect_one_src_two_dst(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst1", gr.null_sink(gr.sizeof_int)) + sfg.define_component("dst2", gr.null_sink(gr.sizeof_int)) + sfg.connect("src", 0, "dst1", 0) + sfg.connect("src", 0, "dst2", 0) + + def test_012_connect_type_mismatch(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst", gr.null_sink(gr.sizeof_char)) + self.assertRaises(ValueError, + lambda: sfg.connect("src", 0, "dst", 0)) + + def test_013_validate(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src", gr.null_source(gr.sizeof_int)) + sfg.define_component("dst1", gr.null_sink(gr.sizeof_int)) + sfg.define_component("dst2", gr.null_sink(gr.sizeof_int)) + sfg.connect("src", 0, "dst1", 0) + sfg.connect("src", 0, "dst2", 0) + sfg.validate() + + def test_014_validate(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src1", gr.null_source (gr.sizeof_int)) + sfg.define_component("nop1", gr.nop (gr.sizeof_int)) + sfg.define_component("dst1", gr.null_sink (gr.sizeof_int)) + sfg.define_component("dst2", gr.null_sink (gr.sizeof_int)) + sfg.connect("src1", 0, "nop1", 0) + sfg.connect("src1", 0, "nop1", 1) + sfg.connect("nop1", 0, "dst1", 0) + sfg.connect("nop1", 1, "dst2", 0) + sfg.validate () + + def test_015_validate(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src1", gr.null_source (gr.sizeof_int)) + sfg.define_component("nop1", gr.nop (gr.sizeof_int)) + sfg.define_component("dst1", gr.null_sink (gr.sizeof_int)) + sfg.define_component("dst2", gr.null_sink (gr.sizeof_int)) + sfg.connect("src1", 0, "nop1", 0) + sfg.connect("src1", 0, "nop1", 2) + sfg.connect("nop1", 0, "dst1", 0) + sfg.connect("nop1", 1, "dst2", 0) + self.assertRaises(RuntimeError, + lambda: sfg.validate ()) + + def test_016_validate(self): + sfg = gr.simple_flowgraph() + sfg.define_component("src1", gr.null_source (gr.sizeof_int)) + sfg.define_component("nop1", gr.nop (gr.sizeof_int)) + sfg.define_component("dst1", gr.null_sink (gr.sizeof_int)) + sfg.define_component("dst2", gr.null_sink (gr.sizeof_int)) + sfg.connect("src1", 0, "nop1", 0) + sfg.connect("src1", 0, "nop1", 1) + sfg.connect("nop1", 0, "dst1", 0) + sfg.connect("nop1", 2, "dst2", 0) + self.assertRaises(RuntimeError, + lambda: sfg.validate ()) + +if __name__ == "__main__": + gr_unittest.main() diff --git a/gnuradio-examples/Makefile.am b/gnuradio-examples/Makefile.am index ad8ca5b1a..6e720ebdd 100644 --- a/gnuradio-examples/Makefile.am +++ b/gnuradio-examples/Makefile.am @@ -21,4 +21,4 @@ include $(top_srcdir)/Makefile.common -SUBDIRS = python +SUBDIRS = python c++ diff --git a/gnuradio-examples/c++/Makefile.am b/gnuradio-examples/c++/Makefile.am new file mode 100644 index 000000000..f25bbaa8f --- /dev/null +++ b/gnuradio-examples/c++/Makefile.am @@ -0,0 +1,27 @@ +# +# Copyright 2006 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 2, 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. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = \ + dialtone \ + hier + diff --git a/gnuradio-examples/c++/dialtone/Makefile.am b/gnuradio-examples/c++/dialtone/Makefile.am new file mode 100644 index 000000000..35e807381 --- /dev/null +++ b/gnuradio-examples/c++/dialtone/Makefile.am @@ -0,0 +1,48 @@ +# +# Copyright 2006 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 2, 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. +# + +include $(top_srcdir)/Makefile.common + +# For compiling within the GNU Radio build tree +INCLUDES=$(STD_DEFINES_AND_INCLUDES) \ + -I$(top_srcdir)/gr-audio-alsa/src + +GR_AUDIO_ALSA_LIBS=$(top_builddir)/gr-audio-alsa/src/libgr_audio_alsa.la + +# For compiling outside the tree, these are the usual +# INCLUDES = -I/usr/local/include -I/usr/local/include/gnuradio +# GNURADIO_CORE_LIBS = -lgnuradio-core +# GR_AUDIO_ALSA_LIBS = -lgr_audio_alsa + +noinst_PROGRAMS = dialtone + +noinst_HEADERS = \ + dialtone.h + +dialtone_SOURCES = \ + dialtone.cc \ + main.cc + +dialtone_LDADD = \ + $(GNURADIO_CORE_LIBS) \ + $(GR_AUDIO_ALSA_LIBS) + +MOSTLYCLEANFILES = *~ diff --git a/gnuradio-examples/c++/dialtone/dialtone.cc b/gnuradio-examples/c++/dialtone/dialtone.cc new file mode 100644 index 000000000..08ecccf75 --- /dev/null +++ b/gnuradio-examples/c++/dialtone/dialtone.cc @@ -0,0 +1,45 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <dialtone.h> +#include <gr_io_signature.h> +#include <gr_sig_source_f.h> +#include <audio_alsa_sink.h> + +// Shared pointer constructor +dialtone_sptr make_dialtone() +{ + return dialtone_sptr(new dialtone()); +} + +// Hierarchical block constructor, with no inputs or outputs +dialtone::dialtone() : +gr_hier_block2("dialtone", + gr_make_io_signature(0,0,0), + gr_make_io_signature(0,0,0)) +{ + define_component("source0", gr_make_sig_source_f(48000, GR_SIN_WAVE, 350, 0.5)); + define_component("source1", gr_make_sig_source_f(48000, GR_SIN_WAVE, 440, 0.5)); + define_component("sink", audio_alsa_make_sink(48000)); + + connect("source0", 0, "sink", 0); + connect("source1", 0, "sink", 1); +} diff --git a/gnuradio-examples/c++/dialtone/dialtone.h b/gnuradio-examples/c++/dialtone/dialtone.h new file mode 100644 index 000000000..2beb46c50 --- /dev/null +++ b/gnuradio-examples/c++/dialtone/dialtone.h @@ -0,0 +1,33 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <gr_hier_block2.h> + +class dialtone; +typedef boost::shared_ptr<dialtone> dialtone_sptr; +dialtone_sptr make_dialtone(); + +class dialtone : public gr_hier_block2 +{ +private: + dialtone(); + friend dialtone_sptr make_dialtone(); +}; diff --git a/gnuradio-examples/c++/dialtone/main.cc b/gnuradio-examples/c++/dialtone/main.cc new file mode 100644 index 000000000..beefac3a5 --- /dev/null +++ b/gnuradio-examples/c++/dialtone/main.cc @@ -0,0 +1,38 @@ +/* + * Copyright 2006 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 2, 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. + */ + +// GNU Radio C++ application +// +// Instantiate a top block +// Instantiate a runtime, passing it the top block +// Tell the runtime to go... + +#include <dialtone.h> +#include <gr_runtime.h> + +int main() +{ + dialtone_sptr top_block = make_dialtone(); + gr_runtime_sptr runtime = gr_make_runtime(top_block); + + runtime->run(); + return 0; +} diff --git a/gnuradio-examples/c++/hier/Makefile.am b/gnuradio-examples/c++/hier/Makefile.am new file mode 100644 index 000000000..f9d341eb7 --- /dev/null +++ b/gnuradio-examples/c++/hier/Makefile.am @@ -0,0 +1,56 @@ +# +# Copyright 2006 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 2, 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. +# + +include $(top_srcdir)/Makefile.common + +# For compiling within the GNU Radio build tree +INCLUDES=$(STD_DEFINES_AND_INCLUDES) \ + -I$(top_srcdir)/gr-audio-alsa/src + +GR_AUDIO_ALSA_LIBS=$(top_builddir)/gr-audio-alsa/src/libgr_audio_alsa.la + +# For compiling outside the tree, these are the usual +# INCLUDES = -I/usr/local/include -I/usr/local/include/gnuradio +# GNURADIO_CORE_LIBS = -lgnuradio-core +# GR_AUDIO_ALSA_LIBS = -lgr_audio_alsa + +noinst_PROGRAMS = dialtone + +noinst_HEADERS = \ + dialtone.h \ + sink.h \ + source.h \ + siggen.h \ + output.h + +dialtone_SOURCES = \ + dialtone.cc \ + source.cc \ + sink.cc \ + siggen.cc \ + output.cc \ + main.cc + +dialtone_LDADD = \ + $(GNURADIO_CORE_LIBS) \ + $(GR_AUDIO_ALSA_LIBS) + +MOSTLYCLEANFILES = *~ diff --git a/gnuradio-examples/c++/hier/dialtone.cc b/gnuradio-examples/c++/hier/dialtone.cc new file mode 100644 index 000000000..eb77cf27b --- /dev/null +++ b/gnuradio-examples/c++/hier/dialtone.cc @@ -0,0 +1,48 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <dialtone.h> +#include <gr_io_signature.h> +#include <source.h> +#include <gr_kludge_copy.h> +#include <sink.h> + +// Shared pointer constructor +dialtone_sptr make_dialtone() +{ + return dialtone_sptr(new dialtone()); +} + +// Hierarchical block constructor, with no inputs or outputs +dialtone::dialtone() : +gr_hier_block2("dialtone", + gr_make_io_signature(0,0,0), + gr_make_io_signature(0,0,0)) +{ + define_component("source", make_source()); + define_component("copy", gr_make_kludge_copy(sizeof(float))); + define_component("sink", make_sink()); + + connect("source", 0, "copy", 0); + connect("source", 1, "copy", 1); + connect("copy", 0, "sink", 0); + connect("copy", 1, "sink", 1); +} diff --git a/gnuradio-examples/c++/hier/dialtone.h b/gnuradio-examples/c++/hier/dialtone.h new file mode 100644 index 000000000..2beb46c50 --- /dev/null +++ b/gnuradio-examples/c++/hier/dialtone.h @@ -0,0 +1,33 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <gr_hier_block2.h> + +class dialtone; +typedef boost::shared_ptr<dialtone> dialtone_sptr; +dialtone_sptr make_dialtone(); + +class dialtone : public gr_hier_block2 +{ +private: + dialtone(); + friend dialtone_sptr make_dialtone(); +}; diff --git a/gnuradio-examples/c++/hier/main.cc b/gnuradio-examples/c++/hier/main.cc new file mode 100644 index 000000000..beefac3a5 --- /dev/null +++ b/gnuradio-examples/c++/hier/main.cc @@ -0,0 +1,38 @@ +/* + * Copyright 2006 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 2, 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. + */ + +// GNU Radio C++ application +// +// Instantiate a top block +// Instantiate a runtime, passing it the top block +// Tell the runtime to go... + +#include <dialtone.h> +#include <gr_runtime.h> + +int main() +{ + dialtone_sptr top_block = make_dialtone(); + gr_runtime_sptr runtime = gr_make_runtime(top_block); + + runtime->run(); + return 0; +} diff --git a/gnuradio-examples/c++/hier/output.cc b/gnuradio-examples/c++/hier/output.cc new file mode 100644 index 000000000..88ee96e58 --- /dev/null +++ b/gnuradio-examples/c++/hier/output.cc @@ -0,0 +1,41 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <output.h> +#include <gr_io_signature.h> +#include <audio_alsa_sink.h> + +// Shared pointer constructor +output_sptr make_output() +{ + return output_sptr(new output()); +} + +output::output() : +gr_hier_block2("output", + gr_make_io_signature(2,2,sizeof(float)), + gr_make_io_signature(0,0,0)) +{ + define_component("audio", audio_alsa_make_sink(48000)); + + connect("self", 0, "audio", 0); + connect("self", 1, "audio", 1); +} diff --git a/gnuradio-examples/c++/hier/output.h b/gnuradio-examples/c++/hier/output.h new file mode 100644 index 000000000..c2f5c99e4 --- /dev/null +++ b/gnuradio-examples/c++/hier/output.h @@ -0,0 +1,33 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <gr_hier_block2.h> + +class output; +typedef boost::shared_ptr<class output> output_sptr; +output_sptr make_output(); + +class output : public gr_hier_block2 +{ +private: + output(); + friend output_sptr make_output(); +}; diff --git a/gnuradio-examples/c++/hier/siggen.cc b/gnuradio-examples/c++/hier/siggen.cc new file mode 100644 index 000000000..f3b4f6733 --- /dev/null +++ b/gnuradio-examples/c++/hier/siggen.cc @@ -0,0 +1,42 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <siggen.h> +#include <gr_io_signature.h> +#include <gr_sig_source_f.h> + +// Shared pointer constructor +siggen_sptr make_siggen() +{ + return siggen_sptr(new siggen()); +} + +siggen::siggen() : +gr_hier_block2("siggen", + gr_make_io_signature(0,0,0), + gr_make_io_signature(2,2,sizeof(float))) +{ + define_component("siggen0", gr_make_sig_source_f(48000, GR_SIN_WAVE, 350, 0.5)); + define_component("siggen1", gr_make_sig_source_f(48000, GR_SIN_WAVE, 440, 0.5)); + + connect("siggen0", 0, "self", 0); + connect("siggen1", 0, "self", 1); +} diff --git a/gnuradio-examples/c++/hier/siggen.h b/gnuradio-examples/c++/hier/siggen.h new file mode 100644 index 000000000..6169882c6 --- /dev/null +++ b/gnuradio-examples/c++/hier/siggen.h @@ -0,0 +1,33 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <gr_hier_block2.h> + +class siggen; +typedef boost::shared_ptr<class siggen> siggen_sptr; +siggen_sptr make_siggen(); + +class siggen : public gr_hier_block2 +{ +private: + siggen(); + friend siggen_sptr make_siggen(); +}; diff --git a/gnuradio-examples/c++/hier/sink.cc b/gnuradio-examples/c++/hier/sink.cc new file mode 100644 index 000000000..f073eb982 --- /dev/null +++ b/gnuradio-examples/c++/hier/sink.cc @@ -0,0 +1,45 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <sink.h> +#include <gr_io_signature.h> +#include <gr_kludge_copy.h> +#include <output.h> + +// Shared pointer constructor +sink_sptr make_sink() +{ + return sink_sptr(new sink()); +} + +sink::sink() : +gr_hier_block2("sink", + gr_make_io_signature(2,2,sizeof(float)), + gr_make_io_signature(0,0,0)) +{ + define_component("copy", gr_make_kludge_copy(sizeof(float))); + define_component("output", make_output()); + + connect("self", 0, "copy", 0); + connect("self", 1, "copy", 1); + connect("copy", 0, "output", 0); + connect("copy", 1, "output", 1); +} diff --git a/gnuradio-examples/c++/hier/sink.h b/gnuradio-examples/c++/hier/sink.h new file mode 100644 index 000000000..5428b59a6 --- /dev/null +++ b/gnuradio-examples/c++/hier/sink.h @@ -0,0 +1,33 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <gr_hier_block2.h> + +class sink; +typedef boost::shared_ptr<sink> sink_sptr; +sink_sptr make_sink(); + +class sink : public gr_hier_block2 +{ +private: + sink(); + friend sink_sptr make_sink(); +}; diff --git a/gnuradio-examples/c++/hier/source.cc b/gnuradio-examples/c++/hier/source.cc new file mode 100644 index 000000000..816f3aa2f --- /dev/null +++ b/gnuradio-examples/c++/hier/source.cc @@ -0,0 +1,41 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <source.h> +#include <gr_io_signature.h> +#include <siggen.h> + +// Shared pointer constructor +source_sptr make_source() +{ + return source_sptr(new source()); +} + +source::source() : +gr_hier_block2("source", + gr_make_io_signature(0,0,0), + gr_make_io_signature(2,2,sizeof(float))) +{ + define_component("siggen", make_siggen()); + + connect("siggen", 0, "self", 0); + connect("siggen", 1, "self", 1); +} diff --git a/gnuradio-examples/c++/hier/source.h b/gnuradio-examples/c++/hier/source.h new file mode 100644 index 000000000..8057726c9 --- /dev/null +++ b/gnuradio-examples/c++/hier/source.h @@ -0,0 +1,33 @@ +/* + * Copyright 2006 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 2, 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. + */ + +#include <gr_hier_block2.h> + +class source; +typedef boost::shared_ptr<source> source_sptr; +source_sptr make_source(); + +class source : public gr_hier_block2 +{ +private: + source(); + friend source_sptr make_source(); +}; diff --git a/gnuradio-examples/python/audio/Makefile.am b/gnuradio-examples/python/audio/Makefile.am index 0a1213c34..3f9b1626c 100644 --- a/gnuradio-examples/python/audio/Makefile.am +++ b/gnuradio-examples/python/audio/Makefile.am @@ -26,6 +26,7 @@ EXTRA_DIST = \ audio_to_file.py \ dial_squelch.py \ dial_tone.py \ + dial_tone2.py \ dialtone_v.py \ mono_tone.py \ multi_tone.py \ diff --git a/gnuradio-examples/python/audio/dial_tone2.py b/gnuradio-examples/python/audio/dial_tone2.py new file mode 100755 index 000000000..a91c6ff4d --- /dev/null +++ b/gnuradio-examples/python/audio/dial_tone2.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,2006 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 2, 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 +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class dial_tone(gr.hier_block2): + def __init__(self): + gr.hier_block2.__init__(self, + "dial_tone", + gr.io_signature(0,0,0), + gr.io_signature(0,0,0)) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + self.define_component("source0", gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)) + self.define_component("source1", gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl)) + self.define_component("dest", audio.sink(sample_rate, options.audio_output)) + self.connect("source0", 0, "dest", 0) + self.connect("source1", 0, "dest", 1) + +if __name__ == '__main__': + top_block = dial_tone() + runtime = gr.runtime(top_block) + + try: + runtime.run() + except KeyboardInterrupt: + runtime.stop() diff --git a/gr-audio-alsa/src/Makefile.am b/gr-audio-alsa/src/Makefile.am index 0f165a0dc..f9b69c78f 100644 --- a/gr-audio-alsa/src/Makefile.am +++ b/gr-audio-alsa/src/Makefile.am @@ -55,8 +55,12 @@ SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) ourlib_LTLIBRARIES = _audio_alsa.la +lib_LTLIBRARIES = libgr_audio_alsa.la + _audio_alsa_la_SOURCES = \ - audio_alsa.cc \ + audio_alsa.cc + +libgr_audio_alsa_la_SOURCES = \ audio_alsa_sink.cc \ audio_alsa_source.cc \ gri_alsa.cc @@ -76,10 +80,16 @@ _audio_alsa_la_LIBADD = \ $(PYTHON_LDFLAGS) \ $(GNURADIO_CORE_LIBS) \ $(ALSA_LIBS) \ + libgr_audio_alsa.la \ -lstdc++ +libgr_audio_alsa_la_LIBADD = \ + $(ALSA_LIBS) + _audio_alsa_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version +libgr_audio_alsa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version + audio_alsa.cc audio_alsa.py: $(LOCAL_IFILES) $(NON_LOCAL_IFILES) $(SWIG) $(SWIGPYTHONARGS) -module audio_alsa -o audio_alsa.cc $(LOCAL_IFILES) |