diff options
Diffstat (limited to 'gnuradio-core/src/lib/runtime')
54 files changed, 3666 insertions, 182 deletions
diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt index 70938a0f17..11bfcfe279 100644 --- a/gnuradio-core/src/lib/runtime/CMakeLists.txt +++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt @@ -90,6 +90,20 @@ list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/gr_select_handler.cc ) +if(ENABLE_GR_CTRLPORT) +list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/ice_application_base.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_ice.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_ice.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_aggregator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_aggregator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_selector.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcpmtconverters_ice.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager.cc +) +endif(ENABLE_GR_CTRLPORT) + + ######################################################################## # Append gnuradio-core test sources ######################################################################## @@ -157,6 +171,28 @@ install(FILES COMPONENT "core_devel" ) + +if(ENABLE_GR_CTRLPORT) +ADD_DEFINITIONS(-DGR_CTRLPORT) +INSTALL(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/ice_application_base.h + ${CMAKE_CURRENT_SOURCE_DIR}/ice_server_template.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpccallbackregister_base.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager_base.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcpmtconverters_ice.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcregisterhelpers.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_aggregator.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_base.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_aggregator.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_base.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_ice.h + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_selector.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) +endif(ENABLE_GR_CTRLPORT) + ######################################################################## # Install swig headers ######################################################################## diff --git a/gnuradio-core/src/lib/runtime/ICE_LICENSE b/gnuradio-core/src/lib/runtime/ICE_LICENSE new file mode 100644 index 0000000000..43ea7572d9 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/ICE_LICENSE @@ -0,0 +1,54 @@ +Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. + +This copy of Ice is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +Ice 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 version +2 along with this program; if not, see http://www.gnu.org/licenses. + +Linking Ice statically or dynamically with other software (such as a +library, module or application) is making a combined work based on Ice. +Thus, the terms and conditions of the GNU General Public License version +2 cover this combined work. + +If such software can only be used together with Ice, then not only the +combined work but the software itself is a work derived from Ice and as +such shall be licensed under the terms of the GNU General Public License +version 2. This includes the situation where Ice is only being used +through an abstraction layer. + +As a special exception to the above, ZeroC grants to the contributors for +the following projects the permission to license their Ice-based software +under the terms of the GNU Lesser General Public License (LGPL) version +2.1 or of the BSD license: + + - Orca Robotics (http://orca-robotics.sourceforge.net) + + - Mumble (http://mumble.sourceforge.net) + +This exception does not extend to the parts of Ice used by these +projects, or to any other derived work: as a whole, any work based on Ice +shall be licensed under the terms and conditions of the GNU General +Public License version 2. + +You may also combine Ice with any software not derived from Ice, provided +the license of such software is compatible with the GNU General Public +License version 2. In addition, as a special exception, ZeroC grants you +permission to combine Ice with: + + - the OpenSSL library, or with a modified version of the OpenSSL library + that uses the same license as OpenSSL + + - any library not derived from Ice and licensed under the terms of + the Apache License, version 2.0 + (http://www.apache.org/licenses/LICENSE-2.0.html) + +If you modify this copy of Ice, you may extend any of the exceptions +provided above to your version of Ice, but you are not obligated to +do so. diff --git a/gnuradio-core/src/lib/runtime/IcePy_Communicator.h b/gnuradio-core/src/lib/runtime/IcePy_Communicator.h new file mode 100644 index 0000000000..d613190d2c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/IcePy_Communicator.h @@ -0,0 +1,35 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPY_COMMUNICATOR_H +#define ICEPY_COMMUNICATOR_H + +#include <Ice/CommunicatorF.h> +#include <gr_core_api.h> + +namespace IcePy +{ + +extern PyTypeObject CommunicatorType; + +GR_CORE_API bool initCommunicator(PyObject*); + +GR_CORE_API Ice::CommunicatorPtr getCommunicator(PyObject*); + +GR_CORE_API PyObject* createCommunicator(const Ice::CommunicatorPtr&); +GR_CORE_API PyObject* getCommunicatorWrapper(const Ice::CommunicatorPtr&); + +} + +extern "C" PyObject* IcePy_initialize(PyObject*, PyObject*); +extern "C" PyObject* IcePy_initializeWithProperties(PyObject*, PyObject*); +extern "C" PyObject* IcePy_initializeWithLogger(PyObject*, PyObject*); +extern "C" PyObject* IcePy_initializeWithPropertiesAndLogger(PyObject*, PyObject*); + +#endif diff --git a/gnuradio-core/src/lib/runtime/frontend.ice b/gnuradio-core/src/lib/runtime/frontend.ice new file mode 100644 index 0000000000..befb5b7a97 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/frontend.ice @@ -0,0 +1,102 @@ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gnuradio.ice> + +[["python:package:gnuradio.ctrlport"]] +module GNURadio { + module Frontend { + + exception NotSupported {}; + exception InvalidSetting { string msg; }; + exception ReceiverFailure { string msg; }; + exception NotExist {}; + dictionary<string, string> TunerArgs; + + struct TunerStatus { + int a2dbits; + float gain; + bool isInverted; + }; + + interface Tuner { + TunerStatus configureTuner(TunerArgs args); //ADDED + idempotent TunerStatus status(); + idempotent float setGain(float gain) throws NotSupported, InvalidSetting; + idempotent bool setInversion(bool inverted) throws NotSupported, InvalidSetting; + }; + + struct ChannelStatus { + string uid; + bool active; + float freq; + float bandwidth; + int payloadBits; + bool isComplex; + string signalName; + }; + + interface Channel extends Component { + idempotent ChannelStatus status(); + idempotent FeedInfo feed(); + idempotent bool active(); + void start(); + void stop(); + idempotent float setCenterFreq(float freq) throws NotSupported, InvalidSetting; + idempotent float setBandwidth(float bw) throws NotSupported, InvalidSetting; + idempotent int setPayloadBits(int bits) throws NotSupported, InvalidSetting; + idempotent bool setComplex(bool complex) throws NotSupported, InvalidSetting; + void removeChannel() throws NotSupported; + }; + + sequence<Tuner*> TunerSeq; + sequence<Channel*> ChannelSeq; + + struct ChannelizerStatus { + string uid; + string signalName; + }; + + interface Channelizer extends Component { + idempotent ChannelizerStatus status(); + idempotent Tuner* getTuner(); + idempotent ChannelSeq getChannels(); + idempotent ChannelSeq getActiveChannels(); + idempotent ChannelSeq getInactiveChannels(); + Channel* createChannel(float freq, float bw, int payloadBits, string address, int port) throws NotSupported; + }; + + sequence<Channelizer*> ChannelizerSeq; + + interface Receiver extends AbstractReceiver { + idempotent ChannelizerSeq getInputs(); +// idempotent ChannelizerSeq getActiveInputs(); +// idempotent ChannelizerSeq getInactiveInputs(); + idempotent Channel* getChannelByID(string id) throws NotExist; + idempotent Channelizer* getChannelizerByID(string id) throws NotExist; + }; + + + }; + + + +}; diff --git a/gnuradio-core/src/lib/runtime/gnuradio.ice b/gnuradio-core/src/lib/runtime/gnuradio.ice new file mode 100644 index 0000000000..971d8fa0e6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gnuradio.ice @@ -0,0 +1,150 @@ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +[["python:package:gnuradio.ctrlport"]] + +#ifndef GNURADIO_DEBUG +#define GNURADIO_DEBUG + +module GNURadio { +class Knob {}; +class KnobB extends Knob { bool value; }; +class KnobC extends Knob { byte value; }; +class KnobI extends Knob { int value; }; +class KnobF extends Knob { float value; }; +class KnobD extends Knob { double value; }; +class KnobL extends Knob { long value; }; +class KnobS extends Knob { string value; }; + +sequence<bool> VectorB; sequence<byte> VectorC; +sequence<int> VectorI; sequence<float> VectorF; +sequence<double> VectorD; sequence<string> VectorS; +sequence<long> VectorL; + +class KnobVecB extends Knob { VectorB value; }; +class KnobVecC extends Knob { VectorC value; }; +class KnobVecI extends Knob { VectorI value; }; +class KnobVecF extends Knob { VectorF value; }; +class KnobVecD extends Knob { VectorD value; }; +class KnobVecL extends Knob { VectorL value; }; +class KnobVecS extends Knob { VectorS value; }; + +enum KnobType { KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT, + KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL, + KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE, + KNOBVECSTRING, KNOBVECLONG }; + +enum DisplayType { + DISPNULL, + DISPTIMESERIESF, + DISPTIMESERIESC, + DISPXYSCATTER, + DISPXYLINE +}; + +struct KnobProp { + KnobType type; + string units; + string description; + DisplayType display; + Knob min; + Knob max; + Knob defaultvalue; +}; + +sequence<string> KnobIDList; +dictionary<string, Knob> KnobMap; +dictionary<string, KnobProp> KnobPropMap; +dictionary<string, string> WaveformArgMap; + +interface StreamReceiver { + void push(VectorC data); +}; + +interface ControlPort { + void set(KnobMap knobs); + idempotent KnobMap get(KnobIDList knobs); + idempotent KnobPropMap properties(KnobIDList knobs); + void shutdown(); + +// string subscribe(StreamReceiver* proxy, string streamName, int requestedPeriod, int RequestedSize); +// idempotent void unsubscribe(string streamID); +}; + +struct FeedInfo { + string protocol; + string address; + string iface; + string port; +}; + +//TODO: convert this part to a Feed Info +struct ReceiverInfo { + string uid; + string signalType; + string signalName; + string allocatableObjectID; + string signalProtocol; + string signalAddress; + string signalInterface; + string signalPort; +}; + +interface Component { + void setName(string newName); +}; + +module Frontend { + interface AbstractReceiver extends Component { + idempotent ReceiverInfo getReceiverInfo(); + }; +}; + +module Booter { + dictionary<string, string> WaveformArgs; + + exception WaveformRunningError { + string waveformClass; + float centerFrequencyHz; + }; + exception SignalSourceError {string msg; }; + + interface WaveformBooter extends Frontend::AbstractReceiver { + string launchWaveform(string waveformClass, WaveformArgs args) + throws WaveformRunningError, SignalSourceError; + +// string launchWaveformWithSession(string waveformClass, WaveformArgs args, IceGrid::Session* session) +// throws WaveformRunningError; + WaveformArgMap getDriverEnum(); + WaveformArgMap getSourceInfo(); + idempotent bool waveformRunning(); + idempotent string getWaveformClass(); + void shutdown(); + }; +}; + +//interface Pingable { +// bool ping(); +//}; + +}; + +#endif diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 6ff57a1d6c..35ea797167 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -30,8 +30,6 @@ #include <sstream> #include <iostream> -using namespace pmt; - static long s_next_id = 0; static long s_ncurrently_allocated = 0; @@ -51,7 +49,8 @@ gr_basic_block::gr_basic_block(const std::string &name, d_symbolic_id(global_block_registry.block_register(this)), d_symbol_name(global_block_registry.register_symbolic_name(this)), d_color(WHITE), - message_subscribers(pmt::pmt_make_dict()) + d_rpc_set(false), + message_subscribers(pmt::make_dict()) { s_ncurrently_allocated++; } @@ -80,7 +79,7 @@ gr_basic_block::set_block_alias(std::string name) void gr_basic_block::message_port_register_in(pmt::pmt_t port_id) { - if(!pmt::pmt_is_symbol(port_id)) { + if(!pmt::is_symbol(port_id)) { throw std::runtime_error("message_port_register_in: bad port id"); } msg_queue[port_id] = msg_queue_t(); @@ -90,10 +89,10 @@ gr_basic_block::message_port_register_in(pmt::pmt_t port_id) pmt::pmt_t gr_basic_block::message_ports_in() { - pmt::pmt_t port_names = pmt::pmt_make_vector(msg_queue.size(), pmt::PMT_NIL); + pmt::pmt_t port_names = pmt::make_vector(msg_queue.size(), pmt::PMT_NIL); msg_queue_map_itr itr = msg_queue.begin(); for(size_t i = 0; i < msg_queue.size(); i++) { - pmt::pmt_vector_set(port_names, i, (*itr).first); + pmt::vector_set(port_names, i, (*itr).first); itr++; } return port_names; @@ -103,23 +102,23 @@ gr_basic_block::message_ports_in() void gr_basic_block::message_port_register_out(pmt::pmt_t port_id) { - if(!pmt::pmt_is_symbol(port_id)) { + if(!pmt::is_symbol(port_id)) { throw std::runtime_error("message_port_register_out: bad port id"); } - if(pmt::pmt_dict_has_key(message_subscribers, port_id)) { + if(pmt::dict_has_key(message_subscribers, port_id)) { throw std::runtime_error("message_port_register_out: port already in use"); } - message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL); + message_subscribers = pmt::dict_add(message_subscribers, port_id, pmt::PMT_NIL); } pmt::pmt_t gr_basic_block::message_ports_out() { - size_t len = pmt::pmt_length(message_subscribers); - pmt::pmt_t port_names = pmt::pmt_make_vector(len, pmt::PMT_NIL); - pmt::pmt_t keys = pmt::pmt_dict_keys(message_subscribers); + size_t len = pmt::length(message_subscribers); + pmt::pmt_t port_names = pmt::make_vector(len, pmt::PMT_NIL); + pmt::pmt_t keys = pmt::dict_keys(message_subscribers); for(size_t i = 0; i < len; i++) { - pmt::pmt_vector_set(port_names, i, pmt::pmt_nth(i, keys)); + pmt::vector_set(port_names, i, pmt::nth(i, keys)); } return port_names; } @@ -127,19 +126,19 @@ gr_basic_block::message_ports_out() // - publish a message on a message port void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) { - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { + if(!pmt::dict_has_key(message_subscribers, port_id)) { throw std::runtime_error("port does not exist"); } - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers, port_id, pmt::PMT_NIL); + pmt::pmt_t currlist = pmt::dict_ref(message_subscribers, port_id, pmt::PMT_NIL); // iterate through subscribers on port - while(pmt::pmt_is_pair(currlist)) { - pmt::pmt_t target = pmt::pmt_car(currlist); + while(pmt::is_pair(currlist)) { + pmt::pmt_t target = pmt::car(currlist); - pmt::pmt_t block = pmt::pmt_car(target); - pmt::pmt_t port = pmt::pmt_cdr(target); + pmt::pmt_t block = pmt::car(target); + pmt::pmt_t port = pmt::cdr(target); - currlist = pmt::pmt_cdr(currlist); + currlist = pmt::cdr(currlist); gr_basic_block_sptr blk = global_block_registry.block_lookup(block); //blk->post(msg); blk->post(port, msg); @@ -149,33 +148,33 @@ void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) // - subscribe to a message port void gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ + if(!pmt::dict_has_key(message_subscribers, port_id)){ std::stringstream ss; - ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " << pmt::write_string(target) << std::endl; throw std::runtime_error(ss.str()); } - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL); // ignore re-adds of the same target - if(!pmt::pmt_list_has(currlist, target)) - message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); + if(!pmt::list_has(currlist, target)) + message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_add(currlist,target)); } void gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ + if(!pmt::dict_has_key(message_subscribers, port_id)){ std::stringstream ss; - ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " << pmt::write_string(target) << std::endl; throw std::runtime_error(ss.str()); } // ignore unsubs of unknown targets - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target)); + pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_rm(currlist,target)); } void -gr_basic_block::_post(pmt_t which_port, pmt_t msg) +gr_basic_block::_post(pmt::pmt_t which_port, pmt::pmt_t msg) { insert_tail(which_port, msg); } @@ -186,7 +185,7 @@ gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) gruel::scoped_lock guard(mutex); if( (msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())){ - std::cout << "target port = " << pmt::pmt_symbol_to_string(which_port) << std::endl; + std::cout << "target port = " << pmt::symbol_to_string(which_port) << std::endl; throw std::runtime_error("attempted to insert_tail on invalid queue!"); } @@ -197,7 +196,7 @@ gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) global_block_registry.notify_blk(alias()); } -pmt_t +pmt::pmt_t gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) { gruel::scoped_lock guard(mutex); @@ -206,13 +205,13 @@ gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) return pmt::pmt_t(); } - pmt_t m(msg_queue[which_port].front()); + pmt::pmt_t m(msg_queue[which_port].front()); msg_queue[which_port].pop_front(); return m; } -pmt_t +pmt::pmt_t gr_basic_block::delete_head_blocking(pmt::pmt_t which_port) { gruel::scoped_lock guard(mutex); @@ -221,7 +220,7 @@ gr_basic_block::delete_head_blocking(pmt::pmt_t which_port) msg_queue_ready[which_port]->wait(guard); } - pmt_t m(msg_queue[which_port].front()); + pmt::pmt_t m(msg_queue[which_port].front()); msg_queue[which_port].pop_front(); return m; } diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index b4935d8ac8..de56954c54 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -38,6 +38,10 @@ #include <boost/thread/condition_variable.hpp> #include <iostream> +#ifdef GR_CTRLPORT +#include <rpcregisterhelpers.h> +#endif + /*! * \brief The abstract base class for all signal processing blocks. * \ingroup internal @@ -56,13 +60,13 @@ class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_ private: //msg_handler_t d_msg_handler; - typedef std::map<pmt::pmt_t , msg_handler_t, pmt::pmt_comperator> d_msg_handlers_t; + typedef std::map<pmt::pmt_t , msg_handler_t, pmt::comperator> d_msg_handlers_t; d_msg_handlers_t d_msg_handlers; typedef std::deque<pmt::pmt_t> msg_queue_t; - typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator> msg_queue_map_t; - typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator>::iterator msg_queue_map_itr; - std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::pmt_comperator> msg_queue_ready; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator> msg_queue_map_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator>::iterator msg_queue_map_itr; + std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::comperator> msg_queue_ready; gruel::mutex mutex; //< protects all vars @@ -81,7 +85,10 @@ class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_ std::string d_symbol_name; std::string d_symbol_alias; vcolor d_color; + bool d_rpc_set; + msg_queue_map_t msg_queue; + std::vector<boost::any> d_rpc_vars; // container for all RPC variables gr_basic_block(void){} //allows pure virtual interface sub-classes @@ -133,7 +140,7 @@ class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_ gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion bool alias_set() { return !d_symbol_alias.empty(); } std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } - pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } + pmt::pmt_t alias_pmt(){ return pmt::intern(alias()); } void set_block_alias(std::string name); // ** Message passing interface ** @@ -205,12 +212,53 @@ class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_ if(msg_queue.find(which_port) != msg_queue.end()){ return true; } - if(pmt::pmt_dict_has_key(message_subscribers, which_port)){ + if(pmt::dict_has_key(message_subscribers, which_port)){ return true; } return false; } - + +#ifdef GR_CTRLPORT + /*! + * \brief Add an RPC variable (get or set). + * + * Using controlport, we create new getters/setters and need to + * store them. Each block has a vector to do this, and these never + * need to be accessed again once they are registered with the RPC + * backend. This function takes a + * boost::shared_sptr<rpcbasic_base> so that when the block is + * deleted, all RPC registered variables are cleaned up. + * + * \param s an rpcbasic_sptr of the new RPC variable register to store. + */ + void add_rpc_variable(rpcbasic_sptr s) + { + d_rpc_vars.push_back(s); + } +#endif /* GR_CTRLPORT */ + + /*! + * \brief Set up the RPC registered variables. + * + * This must be overloaded by a block that wants to use + * controlport. This is where rpcbasic_register_{get,set} pointers + * are created, which then get wrapped as shared pointers + * (rpcbasic_sptr(...)) and stored using add_rpc_variable. + */ + virtual void setup_rpc() {}; + + /*! + * \brief Ask if this block has been registered to the RPC. + * + * We can only register a block once, so we use this to protect us + * from calling it multiple times. + */ + bool is_rpc_set() { return d_rpc_set; } + + /*! + * \brief When the block is registered with the RPC, set this. + */ + void rpc_set() { d_rpc_set = true; } /*! * \brief Confirm that ninputs and noutputs is an acceptable combination. @@ -253,9 +301,6 @@ class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_ * If the block inherits from gr_hier_block2, the runtime system will * ensure that no reentrant calls are made to msg_handler. */ - //template <typename T> void set_msg_handler(T msg_handler){ - // d_msg_handler = msg_handler_t(msg_handler); - //} template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){ if(msg_queue.find(which_port) == msg_queue.end()){ throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); } diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index f52f7a6baa..83bbea37e6 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -45,6 +45,7 @@ gr_block::gr_block (const std::string &name, d_max_noutput_items(0), d_min_noutput_items(0), d_tag_propagation_policy(TPP_ALL_TO_ALL), + d_pc_rpc_set(false), d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) { @@ -347,6 +348,43 @@ gr_block::pc_work_time() } } +void +gr_block::setup_pc_rpc() +{ + d_pc_rpc_set = true; +#ifdef GR_CTRLPORT + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( + alias(), "noutput_items", &gr_block::pc_noutput_items, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "Average noutput items", RPC_PRIVLVL_MIN, DISPTIMESERIESF))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( + alias(), "nproduced", &gr_block::pc_nproduced, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "Average items produced", RPC_PRIVLVL_MIN, DISPTIMESERIESF))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( + alias(), "work time", &gr_block::pc_work_time, + pmt::mp(0), pmt::mp(1e9), pmt::mp(0), + "", "Average clock cycles in call to work", RPC_PRIVLVL_MIN, DISPTIMESERIESF))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( + alias(), "input \% full", &gr_block::pc_input_buffers_full, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "Average of how full input buffers are", RPC_PRIVLVL_MIN, DISPTIMESERIESF))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( + alias(), "output \% full", &gr_block::pc_output_buffers_full, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "Average of how full output buffers are", RPC_PRIVLVL_MIN, DISPTIMESERIESF))); +#endif /* GR_CTRLPORT */ +} + std::ostream& operator << (std::ostream& os, const gr_block *m) { diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index bd9ff42dfd..ee69309169 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -412,6 +412,24 @@ class GR_CORE_API gr_block : public gr_basic_block { */ float pc_work_time(); + /*! + * \brief Sets up export of perf. counters to ControlPort. Only + * called by the scheduler. + */ + void setup_pc_rpc(); + + /*! + * \brief Checks if this block is already exporting perf. counters + * to ControlPort. + */ + bool is_pc_rpc_set() { return d_pc_rpc_set; } + + /*! + * \brief If the block calls this in its constructor, it's + * perf. counters will not be exported. + */ + void no_pc_rpc() { d_pc_rpc_set = true; } + // ---------------------------------------------------------------------------- // Functions to handle thread affinity @@ -450,6 +468,7 @@ class GR_CORE_API gr_block : public gr_basic_block { int d_max_noutput_items; // value of max_noutput_items for this block tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream std::vector<unsigned int> d_affinity; // thread affinity proc. mask + bool d_pc_rpc_set; protected: gr_block (void){} //allows pure virtual interface sub-classes diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc index ff20e0e85a..b151bd96d2 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -28,8 +28,6 @@ #include <gr_buffer.h> #include <iostream> -using namespace pmt; - static long s_ncurrently_allocated = 0; long @@ -151,8 +149,8 @@ gr_block_detail::nitems_written(unsigned int which_output) void gr_block_detail::add_item_tag(unsigned int which_output, const gr_tag_t &tag) { - if(!pmt_is_symbol(tag.key)) { - throw pmt_wrong_type("gr_block_detail::add_item_tag key", tag.key); + if(!pmt::is_symbol(tag.key)) { + throw pmt::wrong_type("gr_block_detail::add_item_tag key", tag.key); } else { // Add tag to gr_buffer's deque tags @@ -163,8 +161,8 @@ gr_block_detail::add_item_tag(unsigned int which_output, const gr_tag_t &tag) void gr_block_detail::remove_item_tag(unsigned int which_input, const gr_tag_t &tag) { - if(!pmt_is_symbol(tag.key)) { - throw pmt_wrong_type("gr_block_detail::add_item_tag key", tag.key); + if(!pmt::is_symbol(tag.key)) { + throw pmt::wrong_type("gr_block_detail::add_item_tag key", tag.key); } else { // Add tag to gr_buffer's deque tags @@ -187,7 +185,7 @@ gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, unsigned int which_input, uint64_t abs_start, uint64_t abs_end, - const pmt_t &key) + const pmt::pmt_t &key) { std::vector<gr_tag_t> found_items; @@ -197,11 +195,11 @@ gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end); // Filter further by key name - pmt_t itemkey; + pmt::pmt_t itemkey; std::vector<gr_tag_t>::iterator itr; for(itr = found_items.begin(); itr != found_items.end(); itr++) { itemkey = (*itr).key; - if(pmt_eqv(key, itemkey)) { + if(pmt::eqv(key, itemkey)) { v.push_back(*itr); } } diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h index a8ed8da908..dd8be71c9c 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -182,7 +182,7 @@ class GR_CORE_API gr_block_detail { float pc_output_buffers_full(size_t which); std::vector<float> pc_output_buffers_full(); float pc_work_time(); - + gr_tpb_detail d_tpb; // used by thread-per-block scheduler int d_produce_or; diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.cc b/gnuradio-core/src/lib/runtime/gr_block_registry.cc index ff23d97eb2..eaa770dcaf 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_registry.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.cc @@ -8,7 +8,7 @@ gr_block_registry global_block_registry; gr_block_registry::gr_block_registry(){ - d_ref_map = pmt::pmt_make_dict(); + d_ref_map = pmt::make_dict(); } long gr_block_registry::block_register(gr_basic_block* block){ @@ -29,9 +29,9 @@ long gr_block_registry::block_register(gr_basic_block* block){ void gr_block_registry::block_unregister(gr_basic_block* block){ d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id())); - d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->symbol_name())); + d_ref_map = pmt::dict_delete(d_ref_map, pmt::intern(block->symbol_name())); if(block->alias_set()){ - d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->alias())); + d_ref_map = pmt::dict_delete(d_ref_map, pmt::intern(block->alias())); } } @@ -44,18 +44,18 @@ std::string gr_block_registry::register_symbolic_name(gr_basic_block* block){ } void gr_block_registry::register_symbolic_name(gr_basic_block* block, std::string name){ - if(pmt_dict_has_key(d_ref_map, pmt::pmt_intern(name))){ + if(dict_has_key(d_ref_map, pmt::intern(name))){ throw std::runtime_error("symbol already exists, can not re-use!"); } - d_ref_map = pmt_dict_add(d_ref_map, pmt::pmt_intern(name), pmt::pmt_make_any(block)); + d_ref_map = dict_add(d_ref_map, pmt::intern(name), pmt::make_any(block)); } gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){ - pmt::pmt_t ref = pmt_dict_ref(d_ref_map, symbol, pmt::PMT_NIL); - if(pmt::pmt_eq(ref, pmt::PMT_NIL)){ + pmt::pmt_t ref = dict_ref(d_ref_map, symbol, pmt::PMT_NIL); + if(pmt::eq(ref, pmt::PMT_NIL)){ throw std::runtime_error("block lookup failed! block not found!"); } - gr_basic_block* blk = boost::any_cast<gr_basic_block*>( pmt::pmt_any_ref(ref) ); + gr_basic_block* blk = boost::any_cast<gr_basic_block*>( pmt::any_ref(ref) ); return blk->shared_from_this(); } diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.h b/gnuradio-core/src/lib/runtime/gr_block_registry.h index 6a2d939e51..2e0a3b6d5c 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_registry.h +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.h @@ -1,14 +1,16 @@ #ifndef GR_BLOCK_REGISTRY_H #define GR_BLOCK_REGISTRY_H +#include <gr_core_api.h> #include <map> +#include <gr_basic_block.h> #ifndef GR_BASIC_BLOCK_H class gr_basic_block; class gr_block; #endif -class gr_block_registry { +class GR_CORE_API gr_block_registry { public: gr_block_registry(); @@ -36,7 +38,7 @@ class gr_block_registry { }; -extern gr_block_registry global_block_registry; +GR_CORE_API extern gr_block_registry global_block_registry; #endif diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc index 9294a5dca2..79b0b0f59d 100644 --- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc @@ -78,7 +78,7 @@ gr_flat_flowgraph::setup_connections() std::cout << boost::format("flat_fg connecting msg primitives: (%s, %s)->(%s, %s)\n") % i->src().block() % i->src().port() % i->dst().block() % i->dst().port(); - i->src().block()->message_port_sub( i->src().port(), pmt::pmt_cons(i->dst().block()->alias_pmt(), i->dst().port()) ); + i->src().block()->message_port_sub( i->src().port(), pmt::cons(i->dst().block()->alias_pmt(), i->dst().port()) ); } } @@ -401,3 +401,15 @@ void gr_flat_flowgraph::replace_endpoint(const gr_msg_endpoint &e, const gr_msg_ } } +void +gr_flat_flowgraph::enable_pc_rpc() +{ +#ifdef GR_PERFORMANCE_COUNTERS + gr_basic_block_viter_t p; + for(p = d_blocks.begin(); p != d_blocks.end(); p++) { + gr_block_sptr block = cast_to_block_sptr(*p); + if(!block->is_pc_rpc_set()) + block->setup_pc_rpc(); + } +#endif /* GR_PERFORMANCE_COUNTERS */ +} diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h index 5c8268d7df..031564f2ec 100644 --- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h @@ -60,6 +60,12 @@ public: void replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src); void clear_endpoint(const gr_msg_endpoint &e, bool is_src); + /*! + * Enables export of perf. counters to ControlPort on all blocks in + * the flowgraph. + */ + void enable_pc_rpc(); + private: gr_flat_flowgraph(); diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flowgraph.h index bef70f626f..3c8cd3cb02 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.h +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.h @@ -73,7 +73,7 @@ public: inline bool gr_msg_endpoint::operator==(const gr_msg_endpoint &other) const { return (d_basic_block == other.d_basic_block && - pmt::pmt_equal(d_port, other.d_port)); + pmt::equal(d_port, other.d_port)); } diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc index 8c2794c63c..9e924fdaf5 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -86,7 +86,7 @@ void gr_hier_block2::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, gr_basic_block_sptr dst, pmt::pmt_t dstport) { - if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); } + if(!pmt::is_symbol(srcport)){throw std::runtime_error("bad port id"); } d_detail->msg_connect(src, srcport, dst, dstport); } @@ -101,7 +101,7 @@ void gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, gr_basic_block_sptr dst, pmt::pmt_t dstport) { - if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); } + if(!pmt::is_symbol(srcport)){throw std::runtime_error("bad port id"); } d_detail->msg_disconnect(src, srcport, dst, dstport); } diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h index f80dd73e4b..aa6b180cac 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -175,28 +175,28 @@ public: return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id); } bool message_port_is_hier_in(pmt::pmt_t port_id){ - return pmt::pmt_list_has(hier_message_ports_in, port_id); + return pmt::list_has(hier_message_ports_in, port_id); } bool message_port_is_hier_out(pmt::pmt_t port_id){ - return pmt::pmt_list_has(hier_message_ports_out, port_id); + return pmt::list_has(hier_message_ports_out, port_id); } pmt::pmt_t hier_message_ports_in; pmt::pmt_t hier_message_ports_out; void message_port_register_hier_in(pmt::pmt_t port_id){ - if(pmt::pmt_list_has(hier_message_ports_in, port_id)) + if(pmt::list_has(hier_message_ports_in, port_id)) throw std::invalid_argument("hier msg in port by this name already registered"); if(msg_queue.find(port_id) != msg_queue.end()) throw std::invalid_argument("block already has a primitive input port by this name"); - hier_message_ports_in = pmt::pmt_list_add(hier_message_ports_in, port_id); + hier_message_ports_in = pmt::list_add(hier_message_ports_in, port_id); } void message_port_register_hier_out(pmt::pmt_t port_id){ - if(pmt::pmt_list_has(hier_message_ports_out, port_id)) + if(pmt::list_has(hier_message_ports_out, port_id)) throw std::invalid_argument("hier msg out port by this name already registered"); - if(pmt::pmt_dict_has_key(message_subscribers, port_id)) + if(pmt::dict_has_key(message_subscribers, port_id)) throw std::invalid_argument("block already has a primitive output port by this name"); - hier_message_ports_out = pmt::pmt_list_add(hier_message_ports_out, port_id); + hier_message_ports_out = pmt::list_add(hier_message_ports_out, port_id); } }; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc index add6da0248..6850afa845 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -154,7 +154,7 @@ gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, // register the subscription // this is done later... -// src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); +// src->message_port_sub(srcport, pmt::cons(dst->alias_pmt(), dstport)); // add block uniquely to list to internal blocks if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ @@ -196,7 +196,7 @@ gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcpor std::cout << "disconnecting message port..." << std::endl; // unregister the subscription - if already subscribed - src->message_port_unsub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); + src->message_port_unsub(srcport, pmt::cons(dst->alias_pmt(), dstport)); // remove edge for this message connection bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; @@ -474,6 +474,23 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const gr_edge_viter_t p; gr_msg_edge_viter_t q,u; + // For every block (gr_block and gr_hier_block2), set up the RPC + // interface. + for(p = edges.begin(); p != edges.end(); p++) { + gr_basic_block_sptr b; + b = p->src().block(); + if(!b->is_rpc_set()) { + b->setup_rpc(); + b->rpc_set(); + } + + b = p->dst().block(); + if(!b->is_rpc_set()) { + b->setup_rpc(); + b->rpc_set(); + } + } + if (GR_HIER_BLOCK2_DETAIL_DEBUG) std::cout << "Flattening stream connections: " << std::endl; diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc index e47473edd8..f41fb4ebd8 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc @@ -113,3 +113,27 @@ gr_top_block::to_top_block() { return cast_to_top_block_sptr(shared_from_this()); } + +void +gr_top_block::setup_rpc() +{ +#ifdef GR_CTRLPORT + // Getters + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, int>( + alias(), "max nouptut_items", + &gr_top_block::max_noutput_items, + pmt::mp(0), pmt::mp(8192), pmt::mp(8192), + "items", "Max number of output items", + RPC_PRIVLVL_MIN, DISPNULL))); + + // Setters + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_set<gr_top_block, int>( + alias(), "max noutput_items", + &gr_top_block::set_max_noutput_items, + pmt::mp(0), pmt::mp(8192), pmt::mp(8192), + "items", "Max number of output items", + RPC_PRIVLVL_MIN, DISPNULL))); +#endif /* GR_CTRLPORT */ +} diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h index 04d1e95e57..10a21a6434 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.h +++ b/gnuradio-core/src/lib/runtime/gr_top_block.h @@ -58,7 +58,7 @@ public: * allowed for any block in the flowgraph. This passes through to * the start function; see that function for more details. */ - void run(int max_noutput_items=100000); + void run(int max_noutput_items=100000000); /*! * Start the contained flowgraph. Creates one or more threads to @@ -71,7 +71,7 @@ public: * always be less than this, but this will cap it as a maximum. Use * this to adjust the maximum latency a flowgraph can exhibit. */ - void start(int max_noutput_items=100000); + void start(int max_noutput_items=100000000); /*! * Stop the running flowgraph. Notifies each thread created by the @@ -123,6 +123,8 @@ public: void set_max_noutput_items(int nmax); gr_top_block_sptr to_top_block(); // Needed for Python type coercion + + void setup_rpc(); }; inline gr_top_block_sptr cast_to_top_block_sptr(gr_basic_block_sptr block) { diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.i b/gnuradio-core/src/lib/runtime/gr_top_block.i index 6ae4c65a99..024582a301 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.i +++ b/gnuradio-core/src/lib/runtime/gr_top_block.i @@ -38,7 +38,7 @@ private: public: ~gr_top_block(); - void start(int max_noutput_items=100000) throw (std::runtime_error); + void start(int max_noutput_items=100000000) throw (std::runtime_error); void stop(); //void wait(); //void run() throw (std::runtime_error); diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc index 4a3694163b..e563fbadb8 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc @@ -108,6 +108,8 @@ gr_top_block_impl::start(int max_noutput_items) d_ffg->validate(); d_ffg->setup_connections(); + d_ffg->enable_pc_rpc(); + d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); d_state = RUNNING; } diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h index f55c3f021b..c49bdabff6 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h @@ -42,7 +42,7 @@ public: ~gr_top_block_impl(); // Create and start scheduler threads - void start(int max_noutput_items=100000); + void start(int max_noutput_items=100000000); // Signal scheduler threads to stop void stop(); diff --git a/gnuradio-core/src/lib/runtime/ice_application_base.cc b/gnuradio-core/src/lib/runtime/ice_application_base.cc new file mode 100644 index 0000000000..88db6056c1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/ice_application_base.cc @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <ice_application_base.h> + +int ice_application_common::d_reacquire_attributes(0); +bool ice_application_common::d_main_called(false); +bool ice_application_common::d_have_ice_config(false); +boost::shared_ptr<boost::thread> ice_application_common::d_thread; +std::string ice_application_common::d_endpointStr(""); + +boost::shared_ptr<ice_application_common> +ice_application_common::Instance() +{ + static boost::shared_ptr<ice_application_common> + instance(new ice_application_common()); + return instance; +} + +int ice_application_common::run(int, char**) +{ + communicator()->waitForShutdown(); + return EXIT_SUCCESS; +} diff --git a/gnuradio-core/src/lib/runtime/ice_application_base.h b/gnuradio-core/src/lib/runtime/ice_application_base.h new file mode 100644 index 0000000000..44671f84b4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/ice_application_base.h @@ -0,0 +1,242 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ICE_APPLICATION_BASE_H +#define ICE_APPLICATION_BASE_H + +#include <gr_core_api.h> +#include <Ice/Ice.h> +#include <boost/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <stdio.h> +#include <iostream> +#include <set> +#include <string> +#include <stdio.h> + +namespace { + static const unsigned int ICEAPPLICATION_ACTIVATION_TIMEOUT_MS(600); +}; + + +class GR_CORE_API ice_application_common : public Ice::Application +{ + public: + template<typename TserverBase, typename TserverClass> friend class ice_application_base; + static boost::shared_ptr<ice_application_common> Instance(); + ~ice_application_common() {;} + static int d_reacquire_attributes; + + protected: + static bool d_main_called, d_have_ice_config; + static std::string d_endpointStr; + static boost::shared_ptr<boost::thread> d_thread; + ice_application_common() {;} + int run(int, char*[]); +}; + +template<typename TserverBase, typename TserverClass> +class ice_application_base +{ +public: + boost::shared_ptr<ice_application_common> d_application; + ice_application_base(TserverClass* _this); + ~ice_application_base() {;} + + static TserverBase* i(); + static const std::vector<std::string> endpoints(); + +protected: + bool have_ice_config() { return d_application->d_have_ice_config; } + void set_endpoint(const std::string& endpoint) { d_application->d_endpointStr = endpoint;} + + //this one is the key... overwrite in templated/inherited variants + virtual TserverBase* i_impl() = 0; + + //tools for the i_impl... + //tell it when it has to resync with the communicator + virtual bool reacquire_sync(); + virtual void sync_reacquire(); + + static TserverClass* d_this; + + int d_reacquire; + //static int d_reacquire_attributes; + +private: + void starticeexample(); + + bool application_started(); + + int run(int, char*[]); + + static void kickoff(); +}; + +template<typename TserverBase, typename TserverClass> +TserverClass* ice_application_base<TserverBase, TserverClass>::d_this(0); + +//template<typename TserverBase, typename TserverClass> +//int ice_application_base<TserverBase, TserverClass>::d_reacquire_attributes(0); + +template<typename TserverBase, typename TserverClass> +ice_application_base<TserverBase, TserverClass>::ice_application_base(TserverClass* _this) + : d_reacquire(0) +{ + //d_reacquire_attributes = 0; + d_this = _this; + d_application = ice_application_common::Instance(); +} + +template<typename TserverBase, typename TserverClass> +void ice_application_base<TserverBase, TserverClass>::starticeexample() +{ + char derp[] = ""; char* argv[2]; argv[0]=derp; + char buf[1024]; buf[0] = 0; + const char iceconf[] = "--Ice.Config="; + FILE *fp; + + sprintf(buf, "/proc/%d/cmdline", getpid()); + + if(NULL == (fp = fopen(buf, "r"))) { + fprintf(stderr, "Cannot open file %s\n", buf); + exit(EXIT_FAILURE); + } + + unsigned int counter(0); + while(fread(buf, 1, 1, fp)) { + if(*buf == iceconf[counter]) { + if(++counter == sizeof(iceconf) - 1) { + int result = fread(buf, sizeof(buf), 1, fp); + if((result == 0) && (feof(fp) == 0)) { + fprintf(stderr, "ICE file read failur %d\n", ferror(fp)); + clearerr(fp); + exit(EXIT_FAILURE); + } + break; + } + } + } + fclose(fp); + + if(buf[0]) { + ice_application_common::d_have_ice_config = true; + ice_application_common::d_main_called = true; + d_application->main(0, argv, buf); + } + else { + ice_application_common::d_have_ice_config = false; + ice_application_common::d_main_called = true; + d_application->main(0, argv); + } +} + +template<typename TserverBase, typename TserverClass> +void ice_application_base<TserverBase, TserverClass>::kickoff() +{ + static bool run_once = false; + + //if(!d_this->application_started()) { + if(!run_once) { + ++d_this->d_application->d_reacquire_attributes; + + ice_application_common::d_thread = boost::shared_ptr<boost::thread> + (new boost::thread(boost::bind(&ice_application_base::starticeexample, d_this))); + + ::timespec timer_ts, rem_ts; + timer_ts.tv_sec = 0; timer_ts.tv_nsec = ICEAPPLICATION_ACTIVATION_TIMEOUT_MS*1000; + + int iter = 0; + while(!d_this->application_started()) { + ::nanosleep(&timer_ts, &rem_ts); + if(!d_this->application_started()) + std::cout << "@"; + if(iter++ > 100) { + std::cout << "ice_application_base::kickoff(), timeout waiting to get communicator() d_application->main() might have failed?!" << std::endl;; + break; + } + } + + run_once = true; + } + + return; +} + + +template<typename TserverBase, typename TserverClass> +bool ice_application_base<TserverBase, TserverClass>::reacquire_sync() +{ + return (d_this->d_reacquire != d_application->d_reacquire_attributes); +} + +template<typename TserverBase, typename TserverClass> +void ice_application_base<TserverBase, TserverClass>::sync_reacquire() +{ + d_this->d_reacquire = d_application->d_reacquire_attributes; +} + + +template<typename TserverBase, typename TserverClass> +const std::vector<std::string> ice_application_base<TserverBase, TserverClass>::endpoints() +{ + std::vector<std::string> ep; ep.push_back(d_this->d_application->d_endpointStr); return ep; +} + +template<typename TserverBase, typename TserverClass> +TserverBase* ice_application_base<TserverBase, TserverClass>::i() +{ + //printf("indacall\n"); + + assert(d_this != 0); + if(!d_this->application_started()) { + //printf("anotherkickoff\n"); + kickoff(); + } + //printf("donekickedoff\n"); + + /*else if(!d_proxy) { + d_proxy = d_this->i_impl(); + assert(d_proxy != 0); + }*/ + + return d_this->i_impl(); +} + +/*template<typename TserverBase, typename TserverClass> + int ice_application_base<TserverBase, TserverClass>::run(int argc, char* argv[]) { + int implreturn(run_impl(argc, argv)); + ice_application_base<TserverBase, TserverClass>::communicator()->waitForShutdown(); + return implreturn; + }*/ + +template<typename TserverBase, typename TImplClass> +bool ice_application_base<TserverBase, TImplClass>::application_started() +{ + return ice_application_base<TserverBase, TImplClass>::d_this->d_application->communicator(); +} + +/*template<typename TserverBase, typename TImplClass> +int ice_application_base<TserverBase, TImplClass>::run_impl(int argc, char* argv[]) { return EXIT_SUCCESS; } +*/ + +#endif diff --git a/gnuradio-core/src/lib/runtime/ice_server_template.h b/gnuradio-core/src/lib/runtime/ice_server_template.h new file mode 100644 index 0000000000..8ddb03cc8e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/ice_server_template.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ICE_SERVER_TEMPLATE_H +#define ICE_SERVER_TEMPLATE_H + +#include <ice_application_base.h> +#include <iostream> + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass> +class ice_server_template : public ice_application_base<TserverBase, TImplClass> +{ +public: + ice_server_template(TImplClass* _this, + const std::string& contolPortName, + const std::string& endpointName); + ~ice_server_template(); + +protected: + //virtual bool application_started(); + TserverBase* i_impl(); + friend class ice_application_base<TserverBase, TImplClass>; + +private: + //virtual int run_impl(int, char*[]); + Ice::ObjectAdapterPtr d_adapter; + TserverBase* d_iceserver; + const std::string d_contolPortName, d_endpointName; +}; + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass> +ice_server_template<TserverBase, TserverClass, TImplClass, TIceClass>::ice_server_template + (TImplClass* _this, const std::string& controlPortName, const std::string& endpointName) + : ice_application_base<TserverBase, TImplClass>(_this), + d_iceserver(0), + d_contolPortName(controlPortName), + d_endpointName(endpointName) +{;} + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass> +ice_server_template<TserverBase, TserverClass,TImplClass, TIceClass>::~ice_server_template() +{ + if(d_adapter) { + d_adapter->deactivate(); + delete(d_iceserver); + d_adapter = 0; + } +} + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass> +TserverBase* ice_server_template<TserverBase, TserverClass, TImplClass, TIceClass>::i_impl() +{ + if(ice_application_base<TserverBase, TImplClass>::d_this->reacquire_sync()) { + d_adapter = (ice_application_base<TserverBase, TImplClass>::d_this->have_ice_config()) ? + ice_application_base<TserverBase, TImplClass>::d_this->d_this->d_application->communicator()->createObjectAdapter(d_contolPortName) : + ice_application_base<TserverBase, TImplClass>::d_this->d_this->d_application->communicator()->createObjectAdapterWithEndpoints(d_contolPortName,"tcp -h *"); + + TserverClass* server_ice(new TserverClass()); + TIceClass obj(server_ice); + + Ice::Identity id(ice_application_base<TserverBase, TImplClass>::d_this->d_this->d_application->communicator()->stringToIdentity(d_endpointName)); + d_adapter->add(obj, id); + d_adapter->activate(); + ice_application_base<TserverBase, TImplClass>::d_this->set_endpoint(ice_application_common::communicator()->proxyToString(d_adapter->createDirectProxy(id))); + + std::cout << std::endl << "Ice Radio Endpoint: " + << ice_server_template<TserverBase, TserverClass, TImplClass, TIceClass>::endpoints()[0] + << std::endl; + + d_iceserver = (TserverBase*) server_ice; + ice_application_base<TserverBase, TImplClass>::d_this->sync_reacquire(); + } + + return d_iceserver; +} + +#endif /* ICE_SERVER_TEMPLATE_H */ diff --git a/gnuradio-core/src/lib/runtime/nop.h b/gnuradio-core/src/lib/runtime/nop.h new file mode 100644 index 0000000000..5b3166da7b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/nop.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_CTRLPORT_NOP_H +#define INCLUDED_CTRLPORT_NOP_H + +#include <ctrlport/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace ctrlport { + + /*! + * \brief A NOP block for testing ctrlport + * + */ + class CTRLPORT_API nop : virtual public gr_sync_block + { + public: + // gr::ctrlport::nop::sptr + typedef boost::shared_ptr<nop> sptr; + + /*! + * Build a simple test block + */ + static sptr make(size_t itemsize, int a, int b); + + virtual void set_a(int b) = 0; + virtual void set_b(int b) = 0; + virtual int a() const = 0; + virtual int b() const = 0; + }; + + } /* namespace ctrlport */ +} /* namespace gr */ + +#endif /* INCLUDED_CTRLPORT_NOP_H */ + diff --git a/gnuradio-core/src/lib/runtime/nop_impl.cc b/gnuradio-core/src/lib/runtime/nop_impl.cc new file mode 100644 index 0000000000..b6764c2257 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/nop_impl.cc @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "nop_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace ctrlport { + + nop::sptr + nop::make(size_t itemsize, int a, int b) + { + return gnuradio::get_initial_sptr + (new nop_impl(itemsize, a, b)); + } + + + nop_impl::nop_impl(size_t itemsize, int a, int b) + : gr_sync_block("nop", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)) + { + set_a(a); + set_b(b); + } + + nop_impl::~nop_impl() + { + } + + void + nop_impl::set_a(int a) + { + d_a = a; + } + + void + nop_impl::set_b(int b) + { + d_b = b; + } + + int + nop_impl::a() const + { + return d_a; + } + + int + nop_impl::b() const + { + return d_b; + } + + int + nop_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + return noutput_items; + } + + void + nop_impl::setup_rpc() + { + d_get_32i_rpcs.push_back(get_32i_sptr + (new get_32i_t(d_name, "a", this, unique_id(), + &nop_impl::a, + pmt::mp(-128), pmt::mp(127), pmt::mp(0), + "", "Value of a", + RPC_PRIVLVL_MIN, DISPTIMESERIESF))); + + d_get_32i_rpcs.push_back(get_32i_sptr + (new get_32i_t(d_name, "b", this, unique_id(), + &nop_impl::b, + pmt::mp(-128), pmt::mp(127), pmt::mp(0), + "", "Value of b", + RPC_PRIVLVL_MIN, DISPTIMESERIESF))); + + d_set_32i_rpcs.push_back(set_32i_sptr + (new set_32i_t(d_name, "a", this, unique_id(), + &nop_impl::set_a, + pmt::mp(-128), pmt::mp(127), pmt::mp(0), + "", "Value of a", + RPC_PRIVLVL_MIN, DISPNULL))); + + d_set_32i_rpcs.push_back(set_32i_sptr + (new set_32i_t(d_name, "b", this, unique_id(), + &nop_impl::set_b, + pmt::mp(-128), pmt::mp(127), pmt::mp(0), + "", "Value of b", + RPC_PRIVLVL_MIN, DISPNULL))); + } + + } /* namespace ctrlport */ +} /* namespace gr */ diff --git a/gnuradio-core/src/lib/runtime/nop_impl.h b/gnuradio-core/src/lib/runtime/nop_impl.h new file mode 100644 index 0000000000..a39ddac8f9 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/nop_impl.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_CTRLPORT_NOP_IMPL_H +#define INCLUDED_CTRLPORT_NOP_IMPL_H + +#include <ctrlport/nop.h> +#include <ctrlport/rpcregisterhelpers.h> +#include <boost/thread/shared_mutex.hpp> + +namespace gr { + namespace ctrlport { + + class CTRLPORT_API nop_impl : public nop + { + private: + typedef rpcbasic_register_get<nop_impl, int> get_32i_t; + typedef rpcbasic_register_set<nop_impl, int> set_32i_t; + + typedef boost::shared_ptr<get_32i_t> get_32i_sptr; + typedef boost::shared_ptr<set_32i_t> set_32i_sptr; + + std::vector<get_32i_sptr> d_get_32i_rpcs; + std::vector<set_32i_sptr> d_set_32i_rpcs; + + void setup_rpc(); + + int d_a, d_b; + + public: + nop_impl(size_t itemsize, int a, int b); + ~nop_impl(); + + void set_a(int a); + void set_b(int b); + int a() const; + int b() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace ctrlport */ +} /* namespace gr */ + +#endif /* INCLUDED_CTRLPORT_NOP_IMPL_H */ + diff --git a/gnuradio-core/src/lib/runtime/pycallback_object.h b/gnuradio-core/src/lib/runtime/pycallback_object.h new file mode 100644 index 0000000000..f6247c0c6d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/pycallback_object.h @@ -0,0 +1,194 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <iostream> +#include <rpcregisterhelpers.h> +#include <ice_application_base.h> +#include <IcePy_Communicator.h> +#include <pythread.h> + +enum pyport_t { + PYPORT_STRING, + PYPORT_FLOAT +}; + +class Instance +{ +public: + static boost::shared_ptr<ice_application_common> get_application() + { + return ice_application_common::Instance(); + } + static Ice::CommunicatorPtr get_swig_communicator() + { + return get_application()->communicator(); + } +}; + +int pycallback_object_count = 500; + +// a simple to-PMT converter template class-function +template <class myType> class pmt_assist +{ +public: + static pmt::pmt_t make(myType _val) + { + return pmt::mp(_val); + } +}; + +/* template specializations for vectors that cant use pmt::mp() */ +template<> +pmt::pmt_t pmt_assist<std::vector<float> >::make(std::vector<float> _val) +{ + return pmt::init_f32vector(_val.size(), &_val[0]); +} + +template<> +pmt::pmt_t pmt_assist<std::vector<gr_complex> >::make(std::vector<gr_complex> _val) +{ + return pmt::init_c32vector(_val.size(), &_val[0]); +} + +template <class myType> class pycallback_object +{ +public: + pycallback_object(std::string name, std::string functionbase, + std::string units, std::string desc, + myType min, myType max, myType deflt, + DisplayType dtype) : + d_callback(NULL), + d_functionbase(functionbase), d_units(units), d_desc(desc), + d_min(min), d_max(max), d_deflt(deflt), d_dtype(dtype) + { + d_callback = NULL; + } + + myType get() { + myType rVal; + if(d_callback == NULL) { + printf("WARNING: pycallback_object get() called without py callback set!\n"); + return rVal; + } + else { + // obtain PyGIL + PyGILState_STATE state = PyGILState_Ensure(); + + PyObject *func; + //PyObject *arglist; + PyObject *result; + + func = (PyObject *) d_callback; // Get Python function + //arglist = Py_BuildValue(""); // Build argument list + result = PyEval_CallObject(func,NULL); // Call Python + //result = PyEval_CallObject(func,arglist); // Call Python + //Py_DECREF(arglist); // Trash arglist + if(result) { // If no errors, return double + rVal = pyCast(result); + } + Py_XDECREF(result); + + // release PyGIL + PyGILState_Release(state); + return rVal; + } + } + + void set_callback(PyObject *cb) + { + d_callback = cb; + } + + void setup_rpc() + { +#ifdef GR_CTRLPORT + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_get<pycallback_object, myType>( + alias(), d_functionbase.c_str(), + &pycallback_object::get, pmt_assist<myType>::make(d_min), + pmt_assist<myType>::make(d_max), pmt_assist<myType>::make(d_deflt), + d_units.c_str(), d_desc.c_str(), RPC_PRIVLVL_MIN, d_dtype))); +#endif /* GR_CTRLPORT */ + } + +private: + PyObject* d_callback; + std::string d_functionbase, d_units, d_desc; + myType d_min, d_max, d_deflt; + DisplayType d_dtype; + + myType pyCast(PyObject* obj) { + printf("TYPE NOT IMPLEMENTED!\n"); + assert(0); + }; +}; + + +// template specialization conversion functions +// get data out of the PyObject and into the real world +template<> +std::string pycallback_object<std::string>::pyCast(PyObject* obj) +{ + return std::string(PyString_AsString(obj)); +} + +template<> +double pycallback_object<double>::pyCast(PyObject* obj) +{ + return PyFloat_AsDouble(obj); +} + +template<> +float pycallback_object<float>::pyCast(PyObject* obj) +{ + return (float)PyFloat_AsDouble(obj); +} + +template<> +int pycallback_object<int>::pyCast(PyObject* obj) +{ + return PyInt_AsLong(obj); +} + +template<> +std::vector<float> pycallback_object<std::vector<float> >::pyCast(PyObject* obj) +{ + int size = PyObject_Size(obj); + std::vector<float> rval(size); + for(int i=0; i<size; i++) { + rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i)); + } + return rval; +} + +template<> +std::vector<gr_complex> pycallback_object<std::vector<gr_complex> >::pyCast(PyObject* obj) +{ + int size = PyObject_Size(obj); + std::vector<gr_complex> rval(size); + for(int i=0; i<size; i++){ rval[i] = \ + gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)), + (float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i))); + } + return rval; +} +// TODO: add more template specializations as needed! diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.cc b/gnuradio-core/src/lib/runtime/qa_block_tags.cc index d6b1065e32..d3ae476027 100644 --- a/gnuradio-core/src/lib/runtime/qa_block_tags.cc +++ b/gnuradio-core/src/lib/runtime/qa_block_tags.cc @@ -31,15 +31,13 @@ #include <gr_head.h> #include <gr_annotator_alltoall.h> #include <gr_annotator_1to1.h> -#include <gr_keep_one_in_n.h> +//#include <gr_keep_one_in_n.h> #include <gr_firdes.h> #include <gr_tags.h> // ---------------------------------------------------------------- -using namespace pmt; - // set to 1 to turn on debug output // The debug output fully checks that the tags seen are what are expected. While // this behavior currently works with our implementation, there is no guarentee @@ -119,39 +117,39 @@ qa_block_tags::t1 () str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt_t expected_tags3[8]; - expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - - pmt_t expected_tags4[8]; - expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); - expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); - expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + pmt::pmt_t expected_tags3[8]; + expected_tags3[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags3[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags3[2] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags3[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags3[4] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags3[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags3[6] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags3[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + + pmt::pmt_t expected_tags4[8]; + expected_tags4[0] = mp(pmt::from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); + expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[2] = mp(pmt::from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[4] = mp(pmt::from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[6] = mp(pmt::from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); + expected_tags4[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); std::cout << std::endl << "qa_block_tags::t1" << std::endl; // For annotator 3, we know it gets tags from ann0 and ann1, test this for(size_t i = 0; i < tags3.size(); i++) { std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags3[i]), pmt::write_string(expected_tags3[i])); } // For annotator 4, we know it gets tags from ann0 and ann2, test this std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); } #endif } @@ -209,33 +207,33 @@ qa_block_tags::t2 () str0 << ann0->name() << ann0->unique_id(); str1 << ann1->name() << ann1->unique_id(); - pmt_t expected_tags2[12]; - expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags2[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags2[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags2[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags2[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags2[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(6)); - expected_tags2[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags2[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags2[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(9)); - expected_tags2[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - expected_tags2[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); - - pmt_t expected_tags4[12]; - expected_tags4[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(2)); - expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags4[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(5)); - expected_tags4[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(8)); - expected_tags4[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags4[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(11)); - expected_tags4[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - expected_tags4[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + pmt::pmt_t expected_tags2[12]; + expected_tags2[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags2[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags2[2] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags2[3] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags2[4] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags2[5] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags2[6] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(6)); + expected_tags2[7] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags2[8] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags2[9] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(9)); + expected_tags2[10] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + expected_tags2[11] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + pmt::pmt_t expected_tags4[12]; + expected_tags4[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(2)); + expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags4[2] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(5)); + expected_tags4[4] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[6] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(8)); + expected_tags4[7] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags4[8] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[9] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(11)); + expected_tags4[10] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + expected_tags4[11] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); std::cout << std::endl << "qa_block_tags::t2" << std::endl; @@ -245,13 +243,13 @@ qa_block_tags::t2 () // inconceivable for ann3 to have it wrong. for(size_t i = 0; i < tags2.size(); i++) { std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags2[i]), pmt::write_string(expected_tags2[i])); } std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); } #endif } @@ -303,39 +301,39 @@ qa_block_tags::t3 () str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt_t expected_tags3[8]; - expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - - pmt_t expected_tags4[8]; - expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); - expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); - expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + pmt::pmt_t expected_tags3[8]; + expected_tags3[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags3[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags3[2] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags3[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags3[4] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags3[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags3[6] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags3[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + + pmt::pmt_t expected_tags4[8]; + expected_tags4[0] = mp(pmt::from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); + expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[2] = mp(pmt::from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[4] = mp(pmt::from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[6] = mp(pmt::from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); + expected_tags4[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); std::cout << std::endl << "qa_block_tags::t3" << std::endl; // For annotator 3, we know it gets tags from ann0 and ann1, test this for(size_t i = 0; i < tags3.size(); i++) { std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags3[i]), pmt::write_string(expected_tags3[i])); } // For annotator 4, we know it gets tags from ann0 and ann2, test this std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); } #endif } @@ -370,6 +368,7 @@ qa_block_tags::t4 () } +/* void qa_block_tags::t5 () { @@ -411,23 +410,23 @@ qa_block_tags::t5 () str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt_t expected_tags1[5]; - expected_tags1[0] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags1[1] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(1)); - expected_tags1[2] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags1[3] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(3)); - - pmt_t expected_tags2[10]; - expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags2[2] = mp(pmt_from_uint64(1000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags2[3] = mp(pmt_from_uint64(1000), mp(str0.str()), mp("seq"), mp(1)); - expected_tags2[4] = mp(pmt_from_uint64(2000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags2[5] = mp(pmt_from_uint64(2000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags2[6] = mp(pmt_from_uint64(3000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags2[7] = mp(pmt_from_uint64(3000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags2[8] = mp(pmt_from_uint64(4000), mp(str1.str()), mp("seq"), mp(4)); - expected_tags2[9] = mp(pmt_from_uint64(4000), mp(str0.str()), mp("seq"), mp(4)); + pmt::pmt_t expected_tags1[5]; + expected_tags1[0] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags1[1] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(1)); + expected_tags1[2] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags1[3] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(3)); + + pmt::pmt_t expected_tags2[10]; + expected_tags2[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags2[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags2[2] = mp(pmt::from_uint64(1000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags2[3] = mp(pmt::from_uint64(1000), mp(str0.str()), mp("seq"), mp(1)); + expected_tags2[4] = mp(pmt::from_uint64(2000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags2[5] = mp(pmt::from_uint64(2000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags2[6] = mp(pmt::from_uint64(3000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags2[7] = mp(pmt::from_uint64(3000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags2[8] = mp(pmt::from_uint64(4000), mp(str1.str()), mp("seq"), mp(4)); + expected_tags2[9] = mp(pmt::from_uint64(4000), mp(str0.str()), mp("seq"), mp(4)); std::cout << std::endl << "qa_block_tags::t5" << std::endl; @@ -435,7 +434,7 @@ qa_block_tags::t5 () std::cout << "tags1.size(): " << tags1.size() << std::endl; for(size_t i = 0; i < tags1.size(); i++) { std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags1[i]), pmt_write_string(expected_tags1[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags1[i]), pmt::write_string(expected_tags1[i])); } // annotator 2 gets tags from annotators 0 and 1 @@ -443,8 +442,8 @@ qa_block_tags::t5 () std::cout << "tags2.size(): " << tags2.size() << std::endl; for(size_t i = 0; i < tags2.size(); i++) { std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i])); + CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags2[i]), pmt::write_string(expected_tags2[i])); } #endif } - +*/ diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.h b/gnuradio-core/src/lib/runtime/qa_block_tags.h index 6b7e5975d1..039d345cdf 100644 --- a/gnuradio-core/src/lib/runtime/qa_block_tags.h +++ b/gnuradio-core/src/lib/runtime/qa_block_tags.h @@ -35,7 +35,7 @@ class qa_block_tags : public CppUnit::TestCase { CPPUNIT_TEST (t2); CPPUNIT_TEST (t3); CPPUNIT_TEST (t4); - CPPUNIT_TEST (t5); + //CPPUNIT_TEST (t5); CPPUNIT_TEST_SUITE_END (); private: @@ -44,7 +44,7 @@ class qa_block_tags : public CppUnit::TestCase { void t2 (); void t3 (); void t4 (); - void t5 (); + //void t5 (); }; diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc index c84a219bd1..ac06a3f8bc 100644 --- a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc +++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc @@ -37,8 +37,6 @@ #define VERBOSE 0 -using namespace pmt; - /* * The gr_nop block has been instrumented so that it counts * the number of messages sent to it. We use this feature @@ -65,9 +63,9 @@ void qa_set_msg_handler::t0() tb->start(); // Send them... - pmt_t port(pmt_intern("port")); + pmt::pmt_t port(pmt::intern("port")); for (int i = 0; i < NMSGS; i++){ - send(nop, port, mp(mp("example-msg"), mp(i))); + send(nop, port, pmt::mp(pmt::mp("example-msg"), pmt::mp(i))); } // Give the messages a chance to be processed diff --git a/gnuradio-core/src/lib/runtime/rpccallbackregister_base.h b/gnuradio-core/src/lib/runtime/rpccallbackregister_base.h new file mode 100644 index 0000000000..c8f60b310c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpccallbackregister_base.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCCALLBACKREGISTER_BASE_H +#define RPCCALLBACKREGISTER_BASE_H + +#include <gruel/msg_accepter.h> +#include <gruel/msg_producer.h> + +enum DisplayType { + DISPNULL, + DISPTIMESERIESF, + DISPTIMESERIESC, + DISPXYSCATTER, + DISPXYLINE +}; + +enum priv_lvl_t { + RPC_PRIVLVL_ALL = 0, + RPC_PRIVLVL_MIN = 9, + RPC_PRIVLVL_NONE = 10 +}; + +enum KnobType { + KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT, + KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL, + KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE, + KNOBVECSTRING, KNOBVECLONG +}; + +struct callbackregister_base +{ + struct callback_base_t + { + public: + callback_base_t(const priv_lvl_t priv_, const std::string& units_, + const DisplayType display_, const std::string& desc_, + const pmt::pmt_t min_, const pmt::pmt_t max_, const pmt::pmt_t def) + : priv(priv_), units(units_), description(desc_), + min(min_), max(max_), defaultvalue(def), display(display_) + { + } + + priv_lvl_t priv; + std::string units, description; + pmt::pmt_t min, max, defaultvalue; + DisplayType display; + }; + + template<typename T, typename Tsptr> + class callback_t : public callback_base_t + { + public: + callback_t(T* callback_, priv_lvl_t priv_, + const std::string& units_, const DisplayType display_, const:: std::string& desc_, + const pmt::pmt_t& min_, const pmt::pmt_t& max_, const pmt::pmt_t& def_) : + callback_base_t(priv_, units_, display_, desc_, min_, max_, def_), + callback(callback_) + { + } + + Tsptr callback; + }; + + typedef callback_t<gruel::msg_accepter, gruel::msg_accepter_sptr> configureCallback_t; + typedef callback_t<gruel::msg_producer, gruel::msg_producer_sptr> queryCallback_t; + + callbackregister_base() {;} + virtual ~callbackregister_base() {;} + + virtual void registerConfigureCallback(const std::string &id, const configureCallback_t callback) = 0; + virtual void unregisterConfigureCallback(const std::string &id) = 0; + virtual void registerQueryCallback(const std::string &id, const queryCallback_t callback) = 0; + virtual void unregisterQueryCallback(const std::string &id) = 0; +}; + +#endif /* RPCCALLBACKREGISTER_BASE_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcmanager.cc b/gnuradio-core/src/lib/runtime/rpcmanager.cc new file mode 100644 index 0000000000..4d164b63f3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcmanager.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcmanager.h> +#include <iostream> +#include <stdexcept> + +bool rpcmanager::booter_registered(false); +bool rpcmanager::aggregator_registered(false); +rpcserver_booter_base* rpcmanager::boot(0); +std::auto_ptr<rpcserver_booter_aggregator> rpcmanager::aggregator(0); + +rpcmanager::rpcmanager() {;} + +rpcmanager::~rpcmanager() +{ + if(boot) + delete boot; +} + +rpcserver_booter_base* +rpcmanager::get() +{ + if(aggregator_registered) { + return aggregator.get(); + } + else if(booter_registered) { + return boot; + } + assert(booter_registered || aggregator_registered); + return boot; +} + +void +rpcmanager::register_booter(rpcserver_booter_base* booter) +{ + if(make_aggregator && !aggregator_registered) { + aggregator.reset(new rpcserver_booter_aggregator()); + aggregator_registered = true; + } + + if(aggregator_registered) { + rpcmanager::rpcserver_booter_base_sptr bootreg(booter); + aggregator->agg()->registerServer(bootreg); + } + else if(!booter_registered) { + boot = booter; + booter_registered = true; + } + else { + throw std::runtime_error("rpcmanager: Aggregator not in use, and a rpc booter is already registered\n"); + } +} diff --git a/gnuradio-core/src/lib/runtime/rpcmanager.h b/gnuradio-core/src/lib/runtime/rpcmanager.h new file mode 100644 index 0000000000..8cb176b2e5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcmanager.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCMANAGER_H +#define RPCMANAGER_H + +#include <gr_core_api.h> +#include <rpcmanager_base.h> +#include <rpcserver_booter_aggregator.h> +#include <memory> +#include <iostream> + +class GR_CORE_API rpcmanager : public virtual rpcmanager_base +{ + public: + rpcmanager(); + ~rpcmanager(); + + static rpcserver_booter_base* get(); + + static void register_booter(rpcserver_booter_base* booter); + + template<typename T> class rpcserver_booter_register_helper + { + public: + rpcserver_booter_register_helper() { + rpcmanager::register_booter(new T()); + } + + //TODO: unregister + }; + + private: + static bool make_aggregator, booter_registered, aggregator_registered; + static void rpcserver_booter_base_sptr_dest( rpcserver_booter_base* b) {;} + static rpcserver_booter_base* boot; + static std::auto_ptr<rpcserver_booter_aggregator> aggregator; +}; + +#endif /* RPCMANAGER_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcmanager_base.h b/gnuradio-core/src/lib/runtime/rpcmanager_base.h new file mode 100644 index 0000000000..60425c4a15 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcmanager_base.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCMANAGER_BASE_H +#define RPCMANAGER_BASE_H + +#include <boost/shared_ptr.hpp> + +class rpcserver_booter_base; +//class rpcserver_booter_aggregator; + +class rpcmanager_base +{ + public: + typedef boost::shared_ptr<rpcserver_booter_base> rpcserver_booter_base_sptr; + + rpcmanager_base() {;} + ~rpcmanager_base() {;} + + //static rpcserver_booter_base* get(); + + //static void register_booter(rpcserver_booter_base_sptr booter); + +private: +}; + +#endif /* RPCMANAGER_BASE_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.cc b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.cc new file mode 100644 index 0000000000..5aa7bc7cbd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.cc @@ -0,0 +1,128 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcpmtconverters_ice.h> +#include <Ice/Ice.h> +#include <gnuradio.h> + +GNURadio::KnobPtr +rpcpmtconverter::from_pmt(const pmt::pmt_t& knob, const Ice::Current& c) +{ + if(pmt::is_real(knob)) { + return new GNURadio::KnobD(Ice::Double(pmt::to_double(knob))); + } + else if(pmt::is_symbol(knob)) { + std::string stuff = pmt::symbol_to_string(knob); + if(stuff.length() != 1) { + return new GNURadio::KnobS(stuff); + } + else { + return new GNURadio::KnobC(stuff[0]); + } + + //TODO: FLOAT!!! + } + else if(pmt::is_integer(knob)) { + return new GNURadio::KnobI(pmt::to_long(knob)); + } + else if(pmt::is_bool(knob)) { + return new GNURadio::KnobB(pmt::to_bool(knob)); + } + else if(pmt::is_uint64(knob)) { + return new GNURadio::KnobL(pmt::to_uint64(knob)); + //const std::complex<float> *c32vector_elements(pmt_t v, size_t &len); //< len is in elements + } + else if(pmt::is_c32vector(knob)) { // c32 sent as interleaved floats + size_t size(pmt::length(knob)); + const float* start((const float*) pmt::c32vector_elements(knob,size)); + return new GNURadio::KnobVecF(std::vector<float>(start,start+size*2)); + } + else if (pmt::is_s32vector(knob)) { + size_t size(pmt::length(knob)); + const int* start((const int*) pmt::s32vector_elements(knob,size)); + return new GNURadio::KnobVecI(std::vector<int>(start,start+size)); + } + else if(pmt::is_f32vector(knob)) { + size_t size(pmt::length(knob)); + const float* start((const float*) pmt::f32vector_elements(knob,size)); + return new GNURadio::KnobVecF(std::vector<float>(start,start+size)); + } + else if (pmt::is_u8vector(knob)) { + size_t size(pmt::length(knob)); + const uint8_t* start((const uint8_t*) pmt::u8vector_elements(knob,size)); + return new GNURadio::KnobVecC(std::vector<Ice::Byte>(start,start+size)); + } + else { + std::cerr << "Error: Don't know how to handle Knob Type (from): " << std::endl; assert(0);} + //TODO: VECTORS!!! + return new GNURadio::Knob(); +} + +pmt::pmt_t +rpcpmtconverter::to_pmt(const GNURadio::KnobPtr& knob, const Ice::Current& c) +{ + std::string id(knob->ice_id(c).substr(12)); + if(id == "KnobD") { + GNURadio::KnobDPtr k(GNURadio::KnobDPtr::dynamicCast(knob)); + return pmt::mp(k->value); + } + else if(id == "KnobF") { + GNURadio::KnobFPtr k(GNURadio::KnobFPtr::dynamicCast(knob)); + return pmt::mp(k->value); + } + else if(id == "KnobI") { + GNURadio::KnobIPtr k(GNURadio::KnobIPtr::dynamicCast(knob)); + return pmt::mp(k->value); + } + else if(id == "KnobS") { + GNURadio::KnobSPtr k(GNURadio::KnobSPtr::dynamicCast(knob)); + return pmt::string_to_symbol(k->value); + } + else if(id == "KnobB") { + GNURadio::KnobBPtr k(GNURadio::KnobBPtr::dynamicCast(knob)); + return pmt::mp(k->value); + } + else if(id == "KnobC") { + GNURadio::KnobCPtr k(GNURadio::KnobCPtr::dynamicCast(knob)); + return pmt::mp(k->value); + } + else if(id == "KnobL") { + GNURadio::KnobLPtr k(GNURadio::KnobLPtr::dynamicCast(knob)); + return pmt::mp((long)k->value); + } else if(id == "KnobVecC") { + GNURadio::KnobVecCPtr k(GNURadio::KnobVecCPtr::dynamicCast(knob)); + return pmt::init_u8vector(k->value.size(), &k->value[0]); + } else if(id == "KnobVecI") { + GNURadio::KnobVecIPtr k(GNURadio::KnobVecIPtr::dynamicCast(knob)); + return pmt::init_s32vector(k->value.size(), &k->value[0]); + } + //else if(id == "KnobVecF") { + // GNURadio::KnobVecFPtr k(GNURadio::KnobVecFPtr::dynamicCast(knob)); + // return pmt::mp(k->value); + //TODO: FLOAT!!! + //TODO: VECTORS!!! + else { + std::cerr << "Error: Don't know how to handle Knob Type: " << id << std::endl; assert(0); + } + + return pmt::pmt_t(); +} diff --git a/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.h b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.h new file mode 100644 index 0000000000..4403b96a2a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.h @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCPMTCONVERTERS_ICE_H +#define RPCPMTCONVERTERS_ICE_H + +#include <gruel/pmt.h> +#include <gnuradio.h> + +namespace rpcpmtconverter +{ + pmt::pmt_t to_pmt(const GNURadio::KnobPtr& knob, const Ice::Current& c); + GNURadio::KnobPtr from_pmt(const pmt::pmt_t& knob, const Ice::Current& c); +} + +#endif /* RPCPMTCONVERTERS_ICE_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcregisterhelpers.h b/gnuradio-core/src/lib/runtime/rpcregisterhelpers.h new file mode 100644 index 0000000000..1be3769ac8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcregisterhelpers.h @@ -0,0 +1,659 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCREGISTERHELPERS_H +#define RPCREGISTERHELPERS_H + +#include <stdio.h> +#include <sstream> +#include <iostream> +#include <rpcserver_booter_base.h> +#include <rpcmanager.h> +#include <rpcserver_selector.h> +#include <rpcserver_base.h> +#include <gr_block_registry.h> + +// Base classes +template<typename T, typename Tto> class rpcextractor_base + : public virtual gruel::msg_accepter +{ +public: + rpcextractor_base(T* source, void (T::*func)(Tto)) : + _source(source), _func(func) {;} + ~rpcextractor_base() {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) { + throw std::runtime_error("rpcextractor_base: no post defined for this data type.\n"); + } + +protected: + T* _source; + void (T::*_func)(Tto); +}; + +template<typename T, typename Tto> +class rpcbasic_extractor : public virtual rpcextractor_base<T,Tto> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(Tto)) : + rpcextractor_base<T,Tto>(source, func) + {;} +}; + +template<typename T, typename Tfrom> +class rpcinserter_base : public virtual gruel::msg_producer +{ +public: + rpcinserter_base(T* source, Tfrom (T::*func)()) : _source(source), _func(func) {;} + rpcinserter_base() {;} + + pmt::pmt_t retrieve() { assert(0); return pmt::pmt_t(); } + +protected: + T* _source; + Tfrom (T::*_func)(); +}; + +template<typename T, typename Tfrom> +class rpcbasic_inserter : + public virtual rpcinserter_base<T,Tfrom> +{ +public: + rpcbasic_inserter(T* source, Tfrom (T::*func)()const) + : rpcinserter_base<T,Tfrom>(source, func) + {;} + + rpcbasic_inserter(T* source, Tfrom (T::*func)()) + : rpcinserter_base<T,Tfrom>(source, func) + {;} + + pmt::pmt_t retrieve() + { + return pmt::mp((rpcinserter_base<T,Tfrom>:: + _source->*rpcinserter_base<T,Tfrom>::_func)()); + } +}; + +// Specialized Extractor Templates +template<typename T> +class rpcbasic_extractor<T,double> : public virtual rpcextractor_base<T,double> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(double)) + : rpcextractor_base<T,double>(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,double>::_source->*rpcextractor_base<T,double>::_func) + (pmt::to_double(msg)); + } +}; + +template<typename T> +class rpcbasic_extractor<T,float> : public virtual rpcextractor_base<T,float> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(float)) + : rpcextractor_base<T,float>(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,float>::_source->*rpcextractor_base<T,float>::_func) + (pmt::to_double(msg)); + } +}; + +template<typename T> +class rpcbasic_extractor<T,long> : public virtual rpcextractor_base<T,long> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(long)) + : rpcextractor_base<T,long>(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,long>::_source->*rpcextractor_base<T,long>::_func) + (pmt::to_long(msg)); + } +}; + +template<typename T> +class rpcbasic_extractor<T,int> : public virtual rpcextractor_base<T,int> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(int)) + : rpcextractor_base<T,int>(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,int>::_source->*rpcextractor_base<T,int>::_func) + (pmt::to_long(msg)); + } +}; + +template<typename T> +class rpcbasic_extractor<T,bool> : public virtual rpcextractor_base<T,bool> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(bool)) + : rpcextractor_base<T,bool>(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,bool>::_source->*rpcextractor_base<T,bool>::_func) + (pmt::to_bool(msg)); + } +}; + +template<typename T> +class rpcbasic_extractor<T,std::complex<double> > + : public virtual rpcextractor_base<T,std::complex<double> > +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(std::complex<double>)) + : rpcextractor_base<T,std::complex<double> >(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,std::complex<double> >:: + _source->*rpcextractor_base<T,std::complex<double> >::_func)(pmt::to_complex(msg)); + } +}; + +template<typename T> +class rpcbasic_extractor<T,std::string> + : public virtual rpcextractor_base<T,std::string> +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(std::string)) + : rpcextractor_base<T,std::string>(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + (rpcextractor_base<T,std::string>:: + _source->*rpcextractor_base<T,std::string>::_func)(pmt::symbol_to_string(msg)); + } +}; + +template<typename T> +class rpcbasic_inserter<T,uint64_t> : public virtual rpcinserter_base<T,uint64_t> +{ +public: + rpcbasic_inserter(T* source, uint64_t (T::*func)() const) + : rpcinserter_base<T,uint64_t>(source, func) + {;} + + rpcbasic_inserter(T* source, uint64_t (T::*func)()) + : rpcinserter_base<T,uint64_t>(source, func) + {;} + + pmt::pmt_t retrieve() + { + return pmt::from_uint64((rpcinserter_base<T,uint64_t>:: + _source->*rpcinserter_base<T,uint64_t>::_func)()); + } +}; + +template<typename T> +class rpcbasic_inserter<T,std::vector< int > > + : public virtual rpcinserter_base<T,std::vector< int > > +{ +public: + rpcbasic_inserter(T* source, std::vector<int > (T::*func)() const) + : rpcinserter_base<T,std::vector<int > >(source, func) + {;} + + rpcbasic_inserter(T* source, std::vector<int > (T::*func)()) + : rpcinserter_base<T,std::vector<int > >(source, func) + {;} + + pmt::pmt_t retrieve() + { + std::vector< int > + vec((rpcinserter_base<T,std::vector<int > >:: + _source->*rpcinserter_base<T,std::vector< int > >::_func)()); + return pmt::init_s32vector(vec.size(), &vec[0]); + } +}; + +template<typename T> +class rpcbasic_inserter<T,std::vector< std::complex<float> > > + : public virtual rpcinserter_base<T,std::vector< std::complex<float> > > +{ +public: + rpcbasic_inserter(T* source, std::vector<std::complex<float> > (T::*func)() const) + : rpcinserter_base<T,std::vector<std::complex<float> > >(source, func) + {;} + + rpcbasic_inserter(T* source, std::vector<std::complex<float> > (T::*func)()) + : rpcinserter_base<T,std::vector<std::complex<float> > >(source, func) + {;} + + pmt::pmt_t retrieve() + { + std::vector< std::complex<float> > + vec((rpcinserter_base<T,std::vector<std::complex<float> > >:: + _source->*rpcinserter_base<T,std::vector< std::complex<float> > >::_func)()); + return pmt::init_c32vector(vec.size(), &vec[0]); + } +}; + +template<typename T> +class rpcbasic_inserter<T,std::vector< float> > + : public virtual rpcinserter_base<T,std::vector< float > > +{ +public: + rpcbasic_inserter(T* source, std::vector<float> (T::*func)() const) + : rpcinserter_base<T,std::vector<float > >(source, func) + {;} + + rpcbasic_inserter(T* source, std::vector<float> (T::*func)()) + : rpcinserter_base<T,std::vector<float> >(source, func) + {;} + + pmt::pmt_t retrieve() + { + std::vector< float > vec((rpcinserter_base<T,std::vector<float> >:: + _source->*rpcinserter_base<T,std::vector< float> >::_func)()); + return pmt::init_f32vector(vec.size(), &vec[0]); + } +}; + +template<typename T> +class rpcbasic_inserter<T,std::vector< uint8_t> > + : public virtual rpcinserter_base<T,std::vector< uint8_t > > { +public: + rpcbasic_inserter(T* source, std::vector<uint8_t> (T::*func)() const) + : rpcinserter_base<T,std::vector<uint8_t > >(source, func) + {;} + + rpcbasic_inserter(T* source, std::vector<uint8_t> (T::*func)()) + : rpcinserter_base<T,std::vector<uint8_t> >(source, func) + {;} + + pmt::pmt_t retrieve() + { + std::vector< uint8_t > vec((rpcinserter_base<T,std::vector<uint8_t> >:: + _source->*rpcinserter_base<T,std::vector< uint8_t> >::_func)()); + return pmt::init_u8vector(vec.size(), &vec[0]); + } +}; + +template <typename T> +struct rpc_register_base +{ + rpc_register_base() {count++;} +protected: static int count; +}; + +// Base class to inherit from and create universal shared pointers. +class rpcbasic_base +{ +public: + rpcbasic_base() {} + virtual ~rpcbasic_base() {}; +}; + +typedef boost::shared_ptr<rpcbasic_base> rpcbasic_sptr; + +template<typename T, typename Tto> +struct rpcbasic_register_set : public rpcbasic_base +{ + // Function used to add a 'set' RPC call using a gr_basic_block's alias. + rpcbasic_register_set(const std::string& block_alias, + const char* functionbase, + void (T::*function)(Tto), + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_ = DISPNULL) + { + d_min = min; + d_max = max; + d_def = def; + d_units = units_; + d_desc = desc_; + d_minpriv = minpriv_; + d_display = display_; + d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); +#ifdef RPCSERVER_ENABLED + callbackregister_base::configureCallback_t + extractor(new rpcbasic_extractor<T,Tto>(d_object, function), + minpriv_, std::string(units_), + display_, std::string(desc_), min, max, def); + std::ostringstream oss(std::ostringstream::out); + oss << block_alias << "::" << functionbase; + d_id = oss.str(); + //std::cerr << "REGISTERING SET: " << d_id << " " << desc_ << std::endl; + rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor); +#endif + } + + // Function used to add a 'set' RPC call using a name and the object + rpcbasic_register_set(const std::string& name, + const char* functionbase, + T* obj, + void (T::*function)(Tto), + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_ = DISPNULL) + { + d_min = min; + d_max = max; + d_def = def; + d_units = units_; + d_desc = desc_; + d_minpriv = minpriv_; + d_display = display_; + d_object = obj; +#ifdef RPCSERVER_ENABLED + callbackregister_base::configureCallback_t + extractor(new rpcbasic_extractor<T,Tto>(d_object, function), + minpriv_, std::string(units_), + display_, std::string(desc_), min, max, def); + std::ostringstream oss(std::ostringstream::out); + oss << name << "::" << functionbase; + d_id = oss.str(); + //std::cerr << "REGISTERING SET: " << d_id << " " << desc_ << std::endl; + rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor); +#endif + } + + ~rpcbasic_register_set() + { +#ifdef RPCSERVER_ENABLED + rpcmanager::get()->i()->unregisterConfigureCallback(d_id); +#endif + } + + + pmt::pmt_t min() const { return d_min; } + pmt::pmt_t max() const { return d_max; } + pmt::pmt_t def() const { return d_def; } + std::string units() const { return d_units; } + std::string description() const { return d_desc; } + priv_lvl_t privilege_level() const { return d_minpriv; } + DisplayType default_display() const { return d_display; } + + void set_min(pmt::pmt_t p) { d_min = p; } + void set_max(pmt::pmt_t p) { d_max = p; } + void set_def(pmt::pmt_t p) { d_def = p; } + void units(std::string u) { d_units = u; } + void description(std::string d) { d_desc = d; } + void privilege_level(priv_lvl_t p) { d_minpriv = p; } + void default_display(DisplayType d) { d_display = d; } + +private: + std::string d_id; + pmt::pmt_t d_min, d_max, d_def; + std::string d_units, d_desc; + priv_lvl_t d_minpriv; + DisplayType d_display; + T *d_object; +}; + + +template<typename T, typename Tfrom> +class rpcbasic_register_get : public rpcbasic_base +{ +public: + // Function used to add a 'set' RPC call using a gr_basic_block's alias. + // primary constructor to allow for T get() functions + rpcbasic_register_get(const std::string& block_alias, + const char* functionbase, + Tfrom (T::*function)(), + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_ = DISPNULL) + { + d_min = min; + d_max = max; + d_def = def; + d_units = units_; + d_desc = desc_; + d_minpriv = minpriv_; + d_display = display_; + d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); +#ifdef RPCSERVER_ENABLED + callbackregister_base::queryCallback_t + inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function), + minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); + std::ostringstream oss(std::ostringstream::out); + oss << block_alias << "::" << functionbase; + d_id = oss.str(); + //std::cerr << "REGISTERING GET: " << d_id << " " << desc_ << std::endl; + rpcmanager::get()->i()->registerQueryCallback(d_id, inserter); +#endif + } + + + // alternate constructor to allow for T get() const functions + rpcbasic_register_get(const std::string& block_alias, + const char* functionbase, + Tfrom (T::*function)() const, + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_ = DISPNULL) + { + d_min = min; + d_max = max; + d_def = def; + d_units = units_; + d_desc = desc_; + d_minpriv = minpriv_; + d_display = display_; + d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); +#ifdef RPCSERVER_ENABLED + callbackregister_base::queryCallback_t + inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function), + minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); + std::ostringstream oss(std::ostringstream::out); + oss << block_alias << "::" << functionbase; + d_id = oss.str(); + //std::cerr << "REGISTERING GET CONST: " << d_id << " " << desc_ << " " << display_ << std::endl; + rpcmanager::get()->i()->registerQueryCallback(d_id, inserter); +#endif + } + + // Function used to add a 'set' RPC call using a name and the object + // primary constructor to allow for T get() functions + rpcbasic_register_get(const std::string& name, + const char* functionbase, + T* obj, + Tfrom (T::*function)(), + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_ = DISPNULL) + { + d_min = min; + d_max = max; + d_def = def; + d_units = units_; + d_desc = desc_; + d_minpriv = minpriv_; + d_display = display_; + d_object = obj; +#ifdef RPCSERVER_ENABLED + callbackregister_base::queryCallback_t + inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function), + minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); + std::ostringstream oss(std::ostringstream::out); + oss << name << "::" << functionbase; + d_id = oss.str(); + //std::cerr << "REGISTERING GET: " << d_id << " " << desc_ << std::endl; + rpcmanager::get()->i()->registerQueryCallback(d_id, inserter); +#endif + } + + + // alternate constructor to allow for T get() const functions + rpcbasic_register_get(const std::string& name, + const char* functionbase, + T* obj, + Tfrom (T::*function)() const, + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_ = DISPNULL) + { + d_min = min; + d_max = max; + d_def = def; + d_units = units_; + d_desc = desc_; + d_minpriv = minpriv_; + d_display = display_; + d_object = obj; +#ifdef RPCSERVER_ENABLED + callbackregister_base::queryCallback_t + inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function), + minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); + std::ostringstream oss(std::ostringstream::out); + oss << name << "::" << functionbase; + d_id = oss.str(); + //std::cerr << "REGISTERING GET CONST: " << d_id << " " << desc_ << " " << display_ << std::endl; + rpcmanager::get()->i()->registerQueryCallback(d_id, inserter); +#endif + } + + ~rpcbasic_register_get() + { +#ifdef RPCSERVER_ENABLED + rpcmanager::get()->i()->unregisterQueryCallback(d_id); +#endif + } + + pmt::pmt_t min() const { return d_min; } + pmt::pmt_t max() const { return d_max; } + pmt::pmt_t def() const { return d_def; } + std::string units() const { return d_units; } + std::string description() const { return d_desc; } + priv_lvl_t privilege_level() const { return d_minpriv; } + DisplayType default_display() const { return d_display; } + + void set_min(pmt::pmt_t p) { d_min = p; } + void set_max(pmt::pmt_t p) { d_max = p; } + void set_def(pmt::pmt_t p) { d_def = p; } + void units(std::string u) { d_units = u; } + void description(std::string d) { d_desc = d; } + void privilege_level(priv_lvl_t p) { d_minpriv = p; } + void default_display(DisplayType d) { d_display = d; } + +private: + std::string d_id; + pmt::pmt_t d_min, d_max, d_def; + std::string d_units, d_desc; + priv_lvl_t d_minpriv; + DisplayType d_display; + T *d_object; +}; + +/* + * This class can wrap a pre-existing variable type for you + * it will define the getter and rpcregister call for you. + * + * It should be used for read-only getters. + * + */ +template<typename Tfrom> +class rpcbasic_register_variable : public rpcbasic_base +{ +protected: + rpcbasic_register_get< rpcbasic_register_variable<Tfrom>, Tfrom > d_rpc_reg; + Tfrom *d_variable; + Tfrom get() { return *d_variable; } +public: + // empty constructor which should never be called but needs to exist for ues in varous STL data structures + void setptr(Tfrom* _variable){ rpcbasic_register_variable<Tfrom>::d_variable = _variable; } + rpcbasic_register_variable() : + d_rpc_reg("FAIL", "FAIL", this, &rpcbasic_register_variable::get, + pmt::PMT_NIL, pmt::PMT_NIL, pmt::PMT_NIL, DISPNULL, + "FAIL", "FAIL", RPC_PRIVLVL_MIN), + d_variable(NULL) + { + throw std::runtime_error("ERROR: rpcbasic_register_variable called with no args. If this happens, someone has tried to use rpcbasic_register_variable incorrectly."); + }; + + rpcbasic_register_variable(const std::string& namebase, + const char* functionbase, + Tfrom *variable, + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN, + DisplayType display_=DISPNULL) : + d_rpc_reg(namebase, functionbase, this, &rpcbasic_register_variable::get, + min, max, def, units_, desc_, minpriv_, display_), + d_variable(variable) + { + //std::cerr << "REGISTERING VAR: " << " " << desc_ << std::endl; + } +}; + +template<typename Tfrom> class rpcbasic_register_variable_rw : public rpcbasic_register_variable<Tfrom> { + private: + rpcbasic_register_set< rpcbasic_register_variable_rw<Tfrom>, Tfrom > d_rpc_regset; + public: + // empty constructor which should never be called but needs to exist for ues in varous STL data structures + rpcbasic_register_variable_rw() : + d_rpc_regset("FAIL","FAIL",this,&rpcbasic_register_variable<Tfrom>::get,pmt::PMT_NIL,pmt::PMT_NIL,pmt::PMT_NIL,DISPNULL,"FAIL","FAIL",RPC_PRIVLVL_MIN) + { + throw std::runtime_error("ERROR: rpcbasic_register_variable_rw called with no args. if this happens someone used rpcbasic_register_variable_rw incorrectly.\n"); + }; + void set(Tfrom _variable){ *(rpcbasic_register_variable<Tfrom>::d_variable) = _variable; } + rpcbasic_register_variable_rw( + const std::string& namebase, + const char* functionbase, + Tfrom *variable, + const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def, + const char* units_ = "", + const char* desc_ = "", + priv_lvl_t minpriv = RPC_PRIVLVL_MIN, + DisplayType display_=DISPNULL) : + rpcbasic_register_variable<Tfrom>(namebase,functionbase,variable,min,max,def,units_,desc_), + d_rpc_regset(namebase,functionbase,this,&rpcbasic_register_variable_rw::set,min,max,def,units_,desc_,minpriv,display_) + { + // no action + } +}; + + + + +#endif diff --git a/gnuradio-core/src/lib/runtime/rpcserver_aggregator.cc b/gnuradio-core/src/lib/runtime/rpcserver_aggregator.cc new file mode 100644 index 0000000000..d750d64905 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_aggregator.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcserver_aggregator.h> +#include <rpcserver_booter_base.h> +#include <iostream> +#include <sstream> +#include <stdexcept> + +rpcserver_aggregator::rpcserver_aggregator() + : d_type(std::string("aggregator")) +{;} + +rpcserver_aggregator::~rpcserver_aggregator() +{;} + +const std::string& +rpcserver_aggregator::type() +{ + return d_type; +} + +const std::vector<std::string>& +rpcserver_aggregator::registeredServers() +{ + return d_registeredServers; +} + +void +rpcserver_aggregator::registerConfigureCallback(const std::string &id, + const configureCallback_t callback) +{ + std::for_each(d_serverlist.begin(), d_serverlist.end(), + registerConfigureCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, configureCallback_t>(id, callback)); +} + +void +rpcserver_aggregator::unregisterConfigureCallback(const std::string &id) +{ + std::for_each(d_serverlist.begin(), d_serverlist.end(), + unregisterConfigureCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, configureCallback_t>(id)); +} + +void +rpcserver_aggregator::registerQueryCallback(const std::string &id, const queryCallback_t callback) +{ + std::for_each(d_serverlist.begin(), d_serverlist.end(), + registerQueryCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, queryCallback_t>(id, callback)); +} + +void +rpcserver_aggregator::unregisterQueryCallback(const std::string &id) +{ + std::for_each(d_serverlist.begin(), d_serverlist.end(), + unregisterQueryCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, queryCallback_t>(id)); +} + +void +rpcserver_aggregator::registerServer(rpcmanager_base::rpcserver_booter_base_sptr server) +{ + std::vector<std::string>::iterator it(std::find(d_registeredServers.begin(), + d_registeredServers.end(), + server->type())); + if(it != d_registeredServers.end()) { + d_serverlist.push_back(server); + d_registeredServers.push_back(server->type()); + } + else { + std::stringstream s; + s << "rpcserver_aggregator::registerServer: server of type " + << server->type() << " already registered" << std::endl; + throw std::runtime_error(s.str().c_str()); + } +} diff --git a/gnuradio-core/src/lib/runtime/rpcserver_aggregator.h b/gnuradio-core/src/lib/runtime/rpcserver_aggregator.h new file mode 100644 index 0000000000..050d9bb1e5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_aggregator.h @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_AGGREGATOR_H +#define RPCSERVER_AGGREGATOR_H + +#include <vector> +#include <string> +#include <rpcserver_base.h> +#include <rpcmanager_base.h> + +class rpcserver_aggregator : public virtual rpcserver_base +{ +public: + rpcserver_aggregator(); + virtual ~rpcserver_aggregator(); + + void registerConfigureCallback(const std::string &id, const configureCallback_t callback); + void unregisterConfigureCallback(const std::string &id); + + void registerQueryCallback(const std::string &id, const queryCallback_t callback); + void unregisterQueryCallback(const std::string &id); + + void registerServer(rpcmanager_base::rpcserver_booter_base_sptr server); + + const std::string& type(); + + const std::vector<std::string>& registeredServers(); + +private: + template<class T, typename Tcallback> + struct registerConfigureCallback_f: public std::unary_function<T,void> + { + registerConfigureCallback_f(const std::string &_id, const Tcallback _callback) + : id(_id), callback(_callback) + {;} + + void operator()(T& x) { x->i()->registerConfigureCallback(id, callback); } + const std::string& id; const Tcallback& callback; + }; + + template<class T, typename Tcallback> + struct unregisterConfigureCallback_f: public std::unary_function<T,void> + { + unregisterConfigureCallback_f(const std::string &_id) + : id(_id) + {;} + + void operator()(T& x) { x->i()->unregisterConfigureCallback(id); } + const std::string& id; + }; + + template<class T, typename Tcallback> + struct registerQueryCallback_f: public std::unary_function<T,void> + { + registerQueryCallback_f(const std::string &_id, const Tcallback _callback) + : id(_id), callback(_callback) + {;} + + void operator()(T& x) { x->i()->registerQueryCallback(id, callback); } + const std::string& id; const Tcallback& callback; + }; + + template<class T, typename Tcallback> + struct unregisterQueryCallback_f: public std::unary_function<T,void> + { + unregisterQueryCallback_f(const std::string &_id) + : id(_id) + {;} + + void operator()(T& x) { x->i()->unregisterQueryCallback(id); } + const std::string& id; + }; + + const std::string d_type; + typedef std::vector<rpcmanager_base::rpcserver_booter_base_sptr> rpcServerMap_t; + std::vector<std::string> d_registeredServers; + rpcServerMap_t d_serverlist; +}; + +#endif /* RPCSERVER_AGGREGATOR_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcserver_base.h b/gnuradio-core/src/lib/runtime/rpcserver_base.h new file mode 100644 index 0000000000..bc985c8d53 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_base.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_BASE_H +#define RPCSERVER_BASE_H + +#include <rpccallbackregister_base.h> + +class rpcserver_base : public virtual callbackregister_base +{ +public: + rpcserver_base() : cur_priv(RPC_PRIVLVL_ALL) {;} + virtual ~rpcserver_base() {;} + + virtual void registerConfigureCallback(const std::string &id, const configureCallback_t callback) = 0; + virtual void unregisterConfigureCallback(const std::string &id) = 0; + virtual void registerQueryCallback(const std::string &id, const queryCallback_t callback) = 0; + virtual void unregisterQueryCallback(const std::string &id) = 0; + virtual void setCurPrivLevel(const priv_lvl_t priv) { cur_priv = priv; } + + typedef boost::shared_ptr<rpcserver_base> rpcserver_base_sptr; +protected: + priv_lvl_t cur_priv; + +private: +}; + +#endif /* RPCSERVER_BASE_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.cc b/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.cc new file mode 100644 index 0000000000..c4c1b03c15 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcserver_booter_aggregator.h> + +rpcserver_booter_aggregator::rpcserver_booter_aggregator() : + d_type(std::string("aggregator")), server(new rpcserver_aggregator()) +{;} + +rpcserver_booter_aggregator::~rpcserver_booter_aggregator() +{;} + +rpcserver_base* +rpcserver_booter_aggregator::i() +{ + return &(*server); +} + +const std::string& +rpcserver_booter_aggregator::type() +{ + return d_type; +} + +const std::vector<std::string> +rpcserver_booter_aggregator::endpoints() +{ + std::vector<std::string> ep; + ep.push_back(std::string("TODO")); + return ep; +} + +const std::vector<std::string>& +rpcserver_booter_aggregator::registeredServers() +{ + return server->registeredServers(); +} + +rpcserver_aggregator* +rpcserver_booter_aggregator::agg() +{ + return &(*server); +} diff --git a/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.h b/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.h new file mode 100644 index 0000000000..da190a0be1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_BOOTER_AGGREGATOR +#define RPCSERVER_BOOTER_AGGREGATOR + +#include <gr_core_api.h> +#include <rpcserver_booter_base.h> +#include <rpcserver_aggregator.h> +#include <boost/shared_ptr.hpp> +#include <string> + +class rpcserver_server; + +class GR_CORE_API rpcserver_booter_aggregator : + public virtual rpcserver_booter_base +{ + public: + rpcserver_booter_aggregator(); + ~rpcserver_booter_aggregator(); + + rpcserver_base* i(); + const std::string& type(); + const std::vector<std::string> endpoints(); + + const std::vector<std::string>& registeredServers(); + + protected: + friend class rpcmanager; + rpcserver_aggregator* agg(); + +private: + std::string d_type; + boost::shared_ptr<rpcserver_aggregator> server; +}; + +#endif /* RPCSERVER_BOOTER_AGGREGATOR */ diff --git a/gnuradio-core/src/lib/runtime/rpcserver_booter_base.h b/gnuradio-core/src/lib/runtime/rpcserver_booter_base.h new file mode 100644 index 0000000000..682944dada --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_booter_base.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_BOOTER_BASE +#define RPCSERVER_BOOTER_BASE + +#include <string> +#include <vector> + +class rpcserver_base; + +class rpcserver_booter_base +{ +public: + rpcserver_booter_base() {;} + virtual ~rpcserver_booter_base() {;} + + virtual rpcserver_base* i()=0; + virtual const std::vector<std::string> endpoints()=0; + virtual const std::string& type()=0; + +private: +}; + +#endif /* RPCSERVER_BOOTER_BASE */ diff --git a/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.cc b/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.cc new file mode 100644 index 0000000000..7cc8cc8938 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.cc @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcserver_ice.h> +#include <rpcserver_booter_ice.h> + +namespace { + static const char* const CONTROL_PORT_CLASS("ice"); + static const char* const CONTROL_PORT_NAME("ControlPort"); + static const char* const ENDPOINT_NAME("gnuradio"); +}; + +rpcserver_booter_ice::rpcserver_booter_ice() : + ice_server_template<rpcserver_base, rpcserver_ice, + rpcserver_booter_ice, GNURadio::ControlPortPtr> + (this, std::string(CONTROL_PORT_NAME), std::string(ENDPOINT_NAME)), + d_type(std::string(CONTROL_PORT_CLASS)) +{;} + +rpcserver_booter_ice::~rpcserver_booter_ice() +{;} + +rpcserver_base* +rpcserver_booter_ice::i() +{ + return ice_server_template<rpcserver_base, rpcserver_ice, + rpcserver_booter_ice, GNURadio::ControlPortPtr>::i(); +} + +const std::vector<std::string> +rpcserver_booter_ice::endpoints() +{ + return ice_server_template<rpcserver_base, rpcserver_ice, + rpcserver_booter_ice, GNURadio::ControlPortPtr>::endpoints(); +} diff --git a/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.h b/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.h new file mode 100644 index 0000000000..69dfcc7602 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_BOOTER_ICE_H +#define RPCSERVER_BOOTER_ICE_H + +#include <rpcserver_booter_base.h> +#include <ice_server_template.h> +#include <gnuradio.h> + +class rpcserver_base; +class rpcserver_ice; + +class rpcserver_booter_ice : public virtual rpcserver_booter_base, + public virtual ice_server_template<rpcserver_base, rpcserver_ice, + rpcserver_booter_ice, GNURadio::ControlPortPtr> +{ +public: + rpcserver_booter_ice(); + ~rpcserver_booter_ice(); + + rpcserver_base* i(); + const std::string & type() {return d_type;} + const std::vector<std::string> endpoints(); + +private: + std::string d_type; +}; + +#endif /* RPCSERVER_BOOTER_ICE_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcserver_ice.cc b/gnuradio-core/src/lib/runtime/rpcserver_ice.cc new file mode 100644 index 0000000000..12229a0688 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_ice.cc @@ -0,0 +1,165 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcserver_ice.h> +#include <IceUtil/IceUtil.h> +#include <Ice/Ice.h> +#include <iostream> +#include <sstream> +#include <stdexcept> +#include <gruel/pmt.h> + +#define DEBUG 0 + +using namespace rpcpmtconverter; + +rpcserver_ice::rpcserver_ice() +{} + +rpcserver_ice::~rpcserver_ice() +{} + +void +rpcserver_ice::registerConfigureCallback(const std::string &id, + const configureCallback_t callback) +{ + { + ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(id)); + if(iter != d_setcallbackmap.end()) { + std::stringstream s; + s << "rpcserver_ice:: rpcserver_ice ERROR registering set, already registered: " + << id << std::endl; + throw std::runtime_error(s.str().c_str()); + } + } + + if(DEBUG) + std::cout << "rpcserver_ice registering set: " << id << std::endl; + + d_setcallbackmap.insert(ConfigureCallbackMap_t::value_type(id, callback)); +} + +void +rpcserver_ice::unregisterConfigureCallback(const std::string &id) +{ + ConfigureCallbackMap_t::iterator iter(d_setcallbackmap.find(id)); + if(iter == d_setcallbackmap.end()) { + std::stringstream s; + s << "rpcserver_ice:: rpcserver_ice ERROR unregistering set, not registered: " + << id << std::endl; + throw std::runtime_error(s.str().c_str()); + } + + if(DEBUG) + std::cout << "rpcserver_ice unregistering set: " << id << std::endl; + + d_setcallbackmap.erase(iter); +} + +void +rpcserver_ice::registerQueryCallback(const std::string &id, + const queryCallback_t callback) +{ + { + QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(id)); + if(iter != d_getcallbackmap.end()) { + std::stringstream s; + s << "rpcserver_ice:: rpcserver_ice ERROR registering get, already registered: " + << id << std::endl; + throw std::runtime_error(s.str().c_str()); + } + } + + if(DEBUG) + std::cout << "rpcserver_ice registering get: " << id << std::endl; + + d_getcallbackmap.insert(QueryCallbackMap_t::value_type(id, callback)); +} + +void +rpcserver_ice::unregisterQueryCallback(const std::string &id) +{ + QueryCallbackMap_t::iterator iter(d_getcallbackmap.find(id)); + if(iter == d_getcallbackmap.end()) { + std::stringstream s; + s << "rpcserver_ice:: rpcserver_ice ERROR unregistering get, registered: " + << id << std::endl; + throw std::runtime_error(s.str().c_str()); + } + + if(DEBUG) + std::cout << "rpcserver_ice unregistering get: " << id << std::endl; + + d_getcallbackmap.erase(iter); +} + +void +rpcserver_ice::set(const GNURadio::KnobMap& knobs, const Ice::Current& c) +{ + std::for_each(knobs.begin(), knobs.end(), + set_f<GNURadio::KnobMap::value_type,ConfigureCallbackMap_t> + (c, d_setcallbackmap, cur_priv)); +} + +GNURadio::KnobMap +rpcserver_ice::get(const GNURadio::KnobIDList& knobs, const Ice::Current& c) +{ + GNURadio::KnobMap outknobs; + + if(knobs.size() == 0) { + std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(), + get_all_f<QueryCallbackMap_t::value_type, QueryCallbackMap_t, GNURadio::KnobMap> + (c, d_getcallbackmap, cur_priv, outknobs)); + } + else { + std::for_each(knobs.begin(), knobs.end(), + get_f<GNURadio::KnobIDList::value_type, QueryCallbackMap_t> + (c, d_getcallbackmap, cur_priv, outknobs)); + } + return outknobs; +} + +GNURadio::KnobPropMap +rpcserver_ice::properties(const GNURadio::KnobIDList& knobs, const Ice::Current& c) +{ + GNURadio::KnobPropMap outknobs; + + if(knobs.size() == 0) { + std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(), + properties_all_f<QueryCallbackMap_t::value_type, + QueryCallbackMap_t,GNURadio::KnobPropMap>(c, d_getcallbackmap, cur_priv, outknobs)); + } + else { + std::for_each(knobs.begin(), knobs.end(), + properties_f<GNURadio::KnobIDList::value_type, + QueryCallbackMap_t, GNURadio::KnobPropMap>(c, d_getcallbackmap, cur_priv, outknobs)); + } + return outknobs; +} + +void +rpcserver_ice::shutdown(const Ice::Current& c) +{ + if(DEBUG) + std::cout << "Shutting down..." << std::endl; + c.adapter->getCommunicator()->shutdown(); +} diff --git a/gnuradio-core/src/lib/runtime/rpcserver_ice.h b/gnuradio-core/src/lib/runtime/rpcserver_ice.h new file mode 100644 index 0000000000..98847bbe05 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_ice.h @@ -0,0 +1,221 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_ICE_H +#define RPCSERVER_ICE_H + +#include <rpcserver_base.h> +#include <rpcpmtconverters_ice.h> +#include <string> +#include <map> +#include <gnuradio.h> +#include <Ice/Exception.h> + +class rpcserver_ice : public virtual rpcserver_base, public GNURadio::ControlPort +{ +public: + rpcserver_ice(); + virtual ~rpcserver_ice(); + + void registerConfigureCallback(const std::string &id, const configureCallback_t callback); + void unregisterConfigureCallback(const std::string &id); + + void registerQueryCallback(const std::string &id, const queryCallback_t callback); + void unregisterQueryCallback(const std::string &id); + + virtual void set(const GNURadio::KnobMap&, const Ice::Current&); + + GNURadio::KnobMap get(const GNURadio::KnobIDList&, const Ice::Current&); + + GNURadio::KnobPropMap properties(const GNURadio::KnobIDList&, const Ice::Current&); + + virtual void shutdown(const Ice::Current&); + +private: + typedef std::map<std::string, configureCallback_t> ConfigureCallbackMap_t; + ConfigureCallbackMap_t d_setcallbackmap; + + typedef std::map<std::string, queryCallback_t> QueryCallbackMap_t; + QueryCallbackMap_t d_getcallbackmap; + + template<typename T, typename TMap> struct set_f + : public std::unary_function<T,void> + { + set_f(const Ice::Current& _c, TMap& _setcallbackmap, const priv_lvl_t& _cur_priv) : + c(_c), d_setcallbackmap(_setcallbackmap), cur_priv(_cur_priv) + {;} + + void operator()(const T& p) + { + ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(p.first)); + if(iter != d_setcallbackmap.end()) { + if(cur_priv <= iter->second.priv) { + (*iter->second.callback).post(pmt::PMT_NIL, rpcpmtconverter::to_pmt(p.second,c)); + } + else { + std::cout << "Key " << p.first << " requires PRIVLVL <= " + << iter->second.priv << " to set, currently at: " + << cur_priv << std::endl; + } + } + else { + throw IceUtil::NullHandleException(__FILE__, __LINE__); + } + } + + const Ice::Current& c; + TMap& d_setcallbackmap; + const priv_lvl_t& cur_priv; + }; + + template<typename T, typename TMap> + struct get_f : public std::unary_function<T,void> + { + get_f(const Ice::Current& _c, TMap& _getcallbackmap, + const priv_lvl_t& _cur_priv, GNURadio::KnobMap& _outknobs) : + c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {} + + void operator()(const T& p) + { + QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(p)); + if(iter != d_getcallbackmap.end()) { + if(cur_priv <= iter->second.priv) { + outknobs[p] = rpcpmtconverter::from_pmt((*iter->second.callback).retrieve(), c); + } + else { + std::cout << "Key " << iter->first << " requires PRIVLVL: <= " + << iter->second.priv << " to get, currently at: " + << cur_priv << std::endl; + } + } + else { + throw IceUtil::NullHandleException(__FILE__, __LINE__); + } + } + + const Ice::Current& c; + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + GNURadio::KnobMap& outknobs; + }; + + template<typename T, typename TMap, typename TKnobMap> + struct get_all_f : public std::unary_function<T,void> + { + get_all_f(const Ice::Current& _c, TMap& _getcallbackmap, + const priv_lvl_t& _cur_priv, TKnobMap& _outknobs) : + c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {;} + + void operator()(const T& p) + { + if(cur_priv <= p.second.priv) { + outknobs[p.first] = rpcpmtconverter::from_pmt(p.second.callback->retrieve(), c); + } + else { + std::cout << "Key " << p.first << " requires PRIVLVL <= " + << p.second.priv << " to get, currently at: " + << cur_priv << std::endl; + } + } + + const Ice::Current& c; + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + TKnobMap& outknobs; + }; + + template<typename T, typename TMap, typename TKnobMap> + struct properties_all_f : public std::unary_function<T,void> + { + properties_all_f(const Ice::Current& _c, QueryCallbackMap_t& _getcallbackmap, + const priv_lvl_t& _cur_priv, GNURadio::KnobPropMap& _outknobs) : + c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {;} + + void operator()(const T& p) + { + if(cur_priv <= p.second.priv) { + GNURadio::KnobProp prop;//(new GNURadio::KnobProp()); + prop.type = GNURadio::KNOBDOUBLE; + prop.units = p.second.units; + prop.description = p.second.description; + prop.min = rpcpmtconverter::from_pmt(p.second.min, c); + prop.max = rpcpmtconverter::from_pmt(p.second.max, c); + prop.display = static_cast<GNURadio::DisplayType>(p.second.display); + outknobs[p.first] = prop; + } + else { + std::cout << "Key " << p.first << " requires PRIVLVL <= " + << p.second.priv << " to get, currently at: " + << cur_priv << std::endl; + } + } + + const Ice::Current& c; + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + TKnobMap& outknobs; + }; + + template<class T, typename TMap, typename TKnobMap> + struct properties_f : public std::unary_function<T,void> + { + properties_f(const Ice::Current& _c, TMap& _getcallbackmap, + const priv_lvl_t& _cur_priv, TKnobMap& _outknobs) : + c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {;} + + void operator()(const T& p) + { + typename TMap::const_iterator iter(d_getcallbackmap.find(p)); + if(iter != d_getcallbackmap.end()) { + if(cur_priv <= iter->second.priv) { + GNURadio::KnobProp prop; + prop.type = GNURadio::KNOBDOUBLE; + prop.units = iter->second.units; + prop.description = iter->second.description; + prop.min = rpcpmtconverter::from_pmt(iter->second.min, c); + prop.max = rpcpmtconverter::from_pmt(iter->second.max, c); + prop.display = static_cast<GNURadio::DisplayType>(iter->second.display); + //outknobs[iter->first] = prop; + outknobs[p] = prop; + } + else { + std::cout << "Key " << iter->first << " requires PRIVLVL: <= " << + iter->second.priv << " to get, currently at: " << cur_priv << std::endl; + } + } + else { + throw IceUtil::NullHandleException(__FILE__, __LINE__); + } + } + + const Ice::Current& c; + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + TKnobMap& outknobs; + }; +}; + +#endif /* RPCSERVER_ICE_H */ diff --git a/gnuradio-core/src/lib/runtime/rpcserver_selector.cc b/gnuradio-core/src/lib/runtime/rpcserver_selector.cc new file mode 100644 index 0000000000..362d5f060a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_selector.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <rpcserver_booter_aggregator.h> +#include <rpcmanager.h> +#include <rpcserver_selector.h> + +bool rpcmanager::make_aggregator(false); + +#ifdef RPCSERVER_ICE + #include <rpcserver_booter_ice.h> + rpcmanager::rpcserver_booter_register_helper<rpcserver_booter_ice> boot_ice; +#endif + +#ifdef RPCSERVER_ERLANG + #error TODO ERLANG +#endif + +#ifdef RPCSERVER_XMLRPC + #error TODO XMLRPC +#endif diff --git a/gnuradio-core/src/lib/runtime/rpcserver_selector.h b/gnuradio-core/src/lib/runtime/rpcserver_selector.h new file mode 100644 index 0000000000..fa63c9a2dc --- /dev/null +++ b/gnuradio-core/src/lib/runtime/rpcserver_selector.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef RPCSERVER_SELECTOR +#define RPCSERVER_SELECTOR + +#define RPCSERVER_ENABLED + +#define RPCSERVER_ICE +//#define RPCSERVER_ERLANG +//#define RPCSERVER_XMLRPC + +#endif diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i index 8e35df8342..f9945e8060 100644 --- a/gnuradio-core/src/lib/runtime/runtime.i +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -67,3 +67,73 @@ %include <gr_sync_decimator.i> %include <gr_sync_interpolator.i> %include <gr_top_block.i> + + +#ifdef GR_CTRLPORT + +enum DisplayType { + DISPNULL, + DISPTIMESERIESF, + DISPTIMESERIESC, + DISPXYSCATTER, + DISPXYLINE +}; + +enum priv_lvl_t { + RPC_PRIVLVL_ALL = 0, + RPC_PRIVLVL_MIN = 9, + RPC_PRIVLVL_NONE = 10 +}; + +enum KnobType { + KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT, + KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL, + KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE, + KNOBVECSTRING, KNOBVECLONG +}; + +%template(StrVector) std::vector<std::string>; + +%{ +#include <rpcserver_booter_base.h> +#include <rpcserver_booter_aggregator.h> +#include <pycallback_object.h> +%} + +%include <rpcserver_booter_base.h> +%include <rpcserver_booter_aggregator.h> +%include <pycallback_object.h> + +// Declare this class here but without the nested templated class +// inside (replaces include of rpcmanager.h) +class GR_CORE_API rpcmanager : public virtual rpcmanager_base +{ + public: + rpcmanager(); + ~rpcmanager(); + + static rpcserver_booter_base* get(); + + static void register_booter(rpcserver_booter_base* booter); +}; + + +// Attach a new python callback method to Python function +%extend pycallback_object { + // Set a Python function object as a callback function + // Note : PyObject *pyfunc is remapped with a typempap + void activate(PyObject *pyfunc) + { + self->set_callback(pyfunc); + Py_INCREF(pyfunc); + } +} + +%template(RPC_get_string) pycallback_object<std::string>; +%template(RPC_get_int) pycallback_object<int>; +%template(RPC_get_float) pycallback_object<float>; +%template(RPC_get_double) pycallback_object<double>; +%template(RPC_get_vector_float) pycallback_object<std::vector<float> >; +%template(RPC_get_vector_gr_complex) pycallback_object<std::vector<gr_complex> >; + +#endif /* GR_CTRLPORT */ |