1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012,2014 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef RPCREGISTERHELPERS_H
24 #define RPCREGISTERHELPERS_H
25 
26 #include <gnuradio/rpcmanager.h>
27 #include <gnuradio/rpcserver_base.h>
28 #include <gnuradio/rpcserver_booter_base.h>
29 #include <gnuradio/rpcserver_selector.h>
30 #include <stdio.h>
31 #include <iostream>
32 #include <sstream>
33 
34 // Fixes circular dependency issue before including block_registry.h
35 class rpcbasic_base;
36 typedef boost::shared_ptr<rpcbasic_base> rpcbasic_sptr;
37 
38 #include <gnuradio/block_registry.h>
39 
40 
41 /*********************************************************************
42  *   RPC Extractor Base Classes
43  ********************************************************************/
44 
45 /*!
46  *\brief Base class for registering a ControlPort Extractor. Acts as
47  *       a message acceptor.
48  */
49 template <typename T, typename Tto>
50 class rpcextractor_base : public virtual gr::messages::msg_accepter
51 {
52 public:
rpcextractor_base(T * source,void (T::* func)(Tto))53     rpcextractor_base(T* source, void (T::*func)(Tto)) : _source(source), _func(func)
54     {
55         ;
56     }
~rpcextractor_base()57     ~rpcextractor_base() { ; }
58 
post(pmt::pmt_t which_port,pmt::pmt_t msg)59     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
60     {
61         (void)which_port;
62         (void)msg;
63         throw std::runtime_error(
64             "rpcextractor_base: no post defined for this data type.\n");
65     }
66 
67 protected:
68     T* _source;
69     void (T::*_func)(Tto);
70 };
71 
72 template <typename T>
73 class rpcextractor_base<T, void> : public virtual gr::messages::msg_accepter
74 {
75 public:
rpcextractor_base(T * source,void (T::* func)())76     rpcextractor_base(T* source, void (T::*func)()) : _source(source), _func(func) { ; }
~rpcextractor_base()77     ~rpcextractor_base() { ; }
78 
post(pmt::pmt_t which_port,pmt::pmt_t msg)79     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
80     {
81         (void)which_port;
82         (void)msg;
83         throw std::runtime_error(
84             "rpcextractor_base: no post defined for this data type.\n");
85     }
86 
87 protected:
88     T* _source;
89     void (T::*_func)();
90 };
91 
92 /*!
93  * \brief Templated parent class for registering a ControlPort Extractor.
94  */
95 template <typename T, typename Tto>
96 class rpcbasic_extractor : public virtual rpcextractor_base<T, Tto>
97 {
98 public:
rpcbasic_extractor(T * source,void (T::* func)(Tto))99     rpcbasic_extractor(T* source, void (T::*func)(Tto))
100         : rpcextractor_base<T, Tto>(source, func)
101     {
102         ;
103     }
104 };
105 
106 
107 /*********************************************************************
108  *   RPC Inserter Base Classes
109  ********************************************************************/
110 
111 /*!
112  * \brief Base class for registering a ControlPort Inserter. Produces a
113  *        message.
114  */
115 template <typename T, typename Tfrom>
116 class rpcinserter_base : public virtual gr::messages::msg_producer
117 {
118 public:
rpcinserter_base(T * source,Tfrom (T::* func)())119     rpcinserter_base(T* source, Tfrom (T::*func)()) : _source(source), _func(func) { ; }
rpcinserter_base()120     rpcinserter_base() { ; }
121 
retrieve()122     pmt::pmt_t retrieve()
123     {
124         assert(0);
125         return pmt::pmt_t();
126     }
127 
128 protected:
129     T* _source;
130     Tfrom (T::*_func)();
131 };
132 
133 
134 /*!
135  * \brief Templated parent class for registering a ControlPort
136  * Inserter.
137  */
138 template <typename T, typename Tfrom>
139 class rpcbasic_inserter : public virtual rpcinserter_base<T, Tfrom>
140 {
141 public:
rpcbasic_inserter(T * source,Tfrom (T::* func)()const)142     rpcbasic_inserter(T* source, Tfrom (T::*func)() const)
143         : rpcinserter_base<T, Tfrom>(source, func)
144     {
145         ;
146     }
147 
rpcbasic_inserter(T * source,Tfrom (T::* func)())148     rpcbasic_inserter(T* source, Tfrom (T::*func)())
149         : rpcinserter_base<T, Tfrom>(source, func)
150     {
151         ;
152     }
153 
retrieve()154     pmt::pmt_t retrieve()
155     {
156         return pmt::mp(
157             (rpcinserter_base<T, Tfrom>::_source->*rpcinserter_base<T, Tfrom>::_func)());
158     }
159 };
160 
161 
162 /*********************************************************************
163  *   RPC Handler Base Classes
164  ********************************************************************/
165 
166 /*!
167  *\brief Base class for registering a ControlPort Handler. Acts as
168  *       a message acceptor.
169  */
170 template <typename T>
171 class rpchandler_base : public virtual gr::messages::msg_accepter
172 {
173 public:
rpchandler_base(T * source,const char * handler)174     rpchandler_base(T* source, const char* handler) : _source(source), _handler(handler)
175     {
176         ;
177     }
~rpchandler_base()178     ~rpchandler_base() { ; }
179 
post(pmt::pmt_t which_port,pmt::pmt_t msg)180     void post(pmt::pmt_t which_port, pmt::pmt_t msg) { _source->post(which_port, msg); }
181 
182 protected:
183     T* _source;
184     const char* _handler;
185 };
186 
187 
188 /*!
189  * \brief Templated parent class for registering a ControlPort Extractor.
190  */
191 template <typename T>
192 class rpcbasic_handler : public virtual rpchandler_base<T>
193 {
194 public:
rpcbasic_handler(T * source,const char * handler)195     rpcbasic_handler(T* source, const char* handler) : rpchandler_base<T>(source, handler)
196     {
197         ;
198     }
199 };
200 
201 
202 /*********************************************************************
203  *   RPC Specialized Extractors
204  ********************************************************************/
205 
206 /*!
207  * \brief Specialized extractor class to make calls to functions that
208  * do not take data (enable, reset, start, etc.).
209  */
210 template <typename T>
211 class rpcbasic_extractor<T, void> : public virtual rpcextractor_base<T, void>
212 {
213 public:
rpcbasic_extractor(T * source,void (T::* func)())214     rpcbasic_extractor(T* source, void (T::*func)())
215         : rpcextractor_base<T, void>(source, func)
216     {
217         ;
218     }
219 
post(pmt::pmt_t which_port,pmt::pmt_t msg)220     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
221     {
222         (void)which_port;
223         (void)msg;
224         (rpcextractor_base<T, void>::_source->*rpcextractor_base<T, void>::_func)();
225     }
226 };
227 
228 /*!
229  * \brief Specialized extractor class for char data.
230  */
231 template <typename T>
232 class rpcbasic_extractor<T, char> : public virtual rpcextractor_base<T, char>
233 {
234 public:
rpcbasic_extractor(T * source,void (T::* func)(char))235     rpcbasic_extractor(T* source, void (T::*func)(char))
236         : rpcextractor_base<T, char>(source, func)
237     {
238         ;
239     }
240 
post(pmt::pmt_t which_port,pmt::pmt_t msg)241     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
242     {
243         (void)which_port;
244         (rpcextractor_base<T, char>::_source->*rpcextractor_base<T, char>::_func)(
245             static_cast<char>(pmt::to_long(msg)));
246     }
247 };
248 
249 /*!
250  * \brief Specialized extractor class for short data.
251  */
252 template <typename T>
253 class rpcbasic_extractor<T, short> : public virtual rpcextractor_base<T, short>
254 {
255 public:
rpcbasic_extractor(T * source,void (T::* func)(short))256     rpcbasic_extractor(T* source, void (T::*func)(short))
257         : rpcextractor_base<T, short>(source, func)
258     {
259         ;
260     }
261 
post(pmt::pmt_t which_port,pmt::pmt_t msg)262     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
263     {
264         (void)which_port;
265         (rpcextractor_base<T, short>::_source->*rpcextractor_base<T, short>::_func)(
266             static_cast<short>(pmt::to_long(msg)));
267     }
268 };
269 
270 /*!
271  * \brief Specialized extractor class for double data.
272  */
273 template <typename T>
274 class rpcbasic_extractor<T, double> : public virtual rpcextractor_base<T, double>
275 {
276 public:
rpcbasic_extractor(T * source,void (T::* func)(double))277     rpcbasic_extractor(T* source, void (T::*func)(double))
278         : rpcextractor_base<T, double>(source, func)
279     {
280         ;
281     }
282 
post(pmt::pmt_t which_port,pmt::pmt_t msg)283     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
284     {
285         (void)which_port;
286         (rpcextractor_base<T, double>::_source->*rpcextractor_base<T, double>::_func)(
287             pmt::to_double(msg));
288     }
289 };
290 
291 /*!
292  * \brief Specialized extractor class for float data.
293  */
294 template <typename T>
295 class rpcbasic_extractor<T, float> : public virtual rpcextractor_base<T, float>
296 {
297 public:
rpcbasic_extractor(T * source,void (T::* func)(float))298     rpcbasic_extractor(T* source, void (T::*func)(float))
299         : rpcextractor_base<T, float>(source, func)
300     {
301         ;
302     }
303 
post(pmt::pmt_t which_port,pmt::pmt_t msg)304     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
305     {
306         (void)which_port;
307         (rpcextractor_base<T, float>::_source->*rpcextractor_base<T, float>::_func)(
308             pmt::to_double(msg));
309     }
310 };
311 
312 /*!
313  * \brief Specialized extractor class for long data.
314  */
315 template <typename T>
316 class rpcbasic_extractor<T, long> : public virtual rpcextractor_base<T, long>
317 {
318 public:
rpcbasic_extractor(T * source,void (T::* func)(long))319     rpcbasic_extractor(T* source, void (T::*func)(long))
320         : rpcextractor_base<T, long>(source, func)
321     {
322         ;
323     }
324 
post(pmt::pmt_t which_port,pmt::pmt_t msg)325     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
326     {
327         (void)which_port;
328         (rpcextractor_base<T, long>::_source->*rpcextractor_base<T, long>::_func)(
329             pmt::to_long(msg));
330     }
331 };
332 
333 /*!
334  * \brief Specialized extractor class for int data.
335  */
336 template <typename T>
337 class rpcbasic_extractor<T, int> : public virtual rpcextractor_base<T, int>
338 {
339 public:
rpcbasic_extractor(T * source,void (T::* func)(int))340     rpcbasic_extractor(T* source, void (T::*func)(int))
341         : rpcextractor_base<T, int>(source, func)
342     {
343         ;
344     }
345 
post(pmt::pmt_t which_port,pmt::pmt_t msg)346     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
347     {
348         (void)which_port;
349         (rpcextractor_base<T, int>::_source->*rpcextractor_base<T, int>::_func)(
350             pmt::to_long(msg));
351     }
352 };
353 
354 /*!
355  * \brief Specialized extractor class for bool data.
356  */
357 template <typename T>
358 class rpcbasic_extractor<T, bool> : public virtual rpcextractor_base<T, bool>
359 {
360 public:
rpcbasic_extractor(T * source,void (T::* func)(bool))361     rpcbasic_extractor(T* source, void (T::*func)(bool))
362         : rpcextractor_base<T, bool>(source, func)
363     {
364         ;
365     }
366 
post(pmt::pmt_t which_port,pmt::pmt_t msg)367     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
368     {
369         (void)which_port;
370         (rpcextractor_base<T, bool>::_source->*rpcextractor_base<T, bool>::_func)(
371             pmt::to_bool(msg));
372     }
373 };
374 
375 /*!
376  * \brief Specialized extractor class for complex (float) data.
377  */
378 template <typename T>
379 class rpcbasic_extractor<T, std::complex<float>>
380     : public virtual rpcextractor_base<T, std::complex<float>>
381 {
382 public:
rpcbasic_extractor(T * source,void (T::* func)(std::complex<float>))383     rpcbasic_extractor(T* source, void (T::*func)(std::complex<float>))
384         : rpcextractor_base<T, std::complex<float>>(source, func)
385     {
386         ;
387     }
388 
post(pmt::pmt_t which_port,pmt::pmt_t msg)389     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
390     {
391         (void)which_port;
392         std::complex<float> k = static_cast<std::complex<float>>(pmt::to_complex(msg));
393         (rpcextractor_base<T, std::complex<float>>::_source
394              ->*rpcextractor_base<T, std::complex<float>>::_func)(k);
395     }
396 };
397 
398 /*!
399  * \brief Specialized extractor class for complex (double) data.
400  */
401 template <typename T>
402 class rpcbasic_extractor<T, std::complex<double>>
403     : public virtual rpcextractor_base<T, std::complex<double>>
404 {
405 public:
rpcbasic_extractor(T * source,void (T::* func)(std::complex<double>))406     rpcbasic_extractor(T* source, void (T::*func)(std::complex<double>))
407         : rpcextractor_base<T, std::complex<double>>(source, func)
408     {
409         ;
410     }
411 
post(pmt::pmt_t which_port,pmt::pmt_t msg)412     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
413     {
414         (void)which_port;
415         (rpcextractor_base<T, std::complex<double>>::_source
416              ->*rpcextractor_base<T, std::complex<double>>::_func)(pmt::to_complex(msg));
417     }
418 };
419 
420 /*!
421  * \brief Specialized extractor class for string data.
422  */
423 template <typename T>
424 class rpcbasic_extractor<T, std::string>
425     : public virtual rpcextractor_base<T, std::string>
426 {
427 public:
rpcbasic_extractor(T * source,void (T::* func)(std::string))428     rpcbasic_extractor(T* source, void (T::*func)(std::string))
429         : rpcextractor_base<T, std::string>(source, func)
430     {
431         ;
432     }
433 
post(pmt::pmt_t which_port,pmt::pmt_t msg)434     void post(pmt::pmt_t which_port, pmt::pmt_t msg)
435     {
436         (void)which_port;
437         (rpcextractor_base<T, std::string>::_source
438              ->*rpcextractor_base<T, std::string>::_func)(pmt::symbol_to_string(msg));
439     }
440 };
441 
442 
443 /*********************************************************************
444  *   RPC Specialized Inserters
445  ********************************************************************/
446 
447 /*!
448  * \brief Specialized inserter class for uint64_t data.
449  */
450 template <typename T>
451 class rpcbasic_inserter<T, uint64_t> : public virtual rpcinserter_base<T, uint64_t>
452 {
453 public:
rpcbasic_inserter(T * source,uint64_t (T::* func)()const)454     rpcbasic_inserter(T* source, uint64_t (T::*func)() const)
455         : rpcinserter_base<T, uint64_t>(source, func)
456     {
457         ;
458     }
459 
rpcbasic_inserter(T * source,uint64_t (T::* func)())460     rpcbasic_inserter(T* source, uint64_t (T::*func)())
461         : rpcinserter_base<T, uint64_t>(source, func)
462     {
463         ;
464     }
465 
retrieve()466     pmt::pmt_t retrieve()
467     {
468         return pmt::from_uint64((rpcinserter_base<T, uint64_t>::_source
469                                      ->*rpcinserter_base<T, uint64_t>::_func)());
470     }
471 };
472 
473 /*!
474  * \brief Specialized inserter class for vectors of signed char data.
475  */
476 template <typename T>
477 class rpcbasic_inserter<T, std::vector<signed char>>
478     : public virtual rpcinserter_base<T, std::vector<signed char>>
479 {
480 public:
rpcbasic_inserter(T * source,std::vector<signed char> (T::* func)()const)481     rpcbasic_inserter(T* source, std::vector<signed char> (T::*func)() const)
482         : rpcinserter_base<T, std::vector<signed char>>(source, func)
483     {
484         ;
485     }
486 
rpcbasic_inserter(T * source,std::vector<signed char> (T::* func)())487     rpcbasic_inserter(T* source, std::vector<signed char> (T::*func)())
488         : rpcinserter_base<T, std::vector<signed char>>(source, func)
489     {
490         ;
491     }
492 
retrieve()493     pmt::pmt_t retrieve()
494     {
495         std::vector<signed char> vec(
496             (rpcinserter_base<T, std::vector<signed char>>::_source
497                  ->*rpcinserter_base<T, std::vector<signed char>>::_func)());
498         return pmt::init_s8vector(vec.size(), &vec[0]);
499     }
500 };
501 
502 /*!
503  * \brief Specialized inserter class for vectors of short data.
504  */
505 template <typename T>
506 class rpcbasic_inserter<T, std::vector<short>>
507     : public virtual rpcinserter_base<T, std::vector<short>>
508 {
509 public:
rpcbasic_inserter(T * source,std::vector<short> (T::* func)()const)510     rpcbasic_inserter(T* source, std::vector<short> (T::*func)() const)
511         : rpcinserter_base<T, std::vector<short>>(source, func)
512     {
513         ;
514     }
515 
rpcbasic_inserter(T * source,std::vector<short> (T::* func)())516     rpcbasic_inserter(T* source, std::vector<short> (T::*func)())
517         : rpcinserter_base<T, std::vector<short>>(source, func)
518     {
519         ;
520     }
521 
retrieve()522     pmt::pmt_t retrieve()
523     {
524         std::vector<short> vec((rpcinserter_base<T, std::vector<short>>::_source
525                                     ->*rpcinserter_base<T, std::vector<short>>::_func)());
526         return pmt::init_s16vector(vec.size(), &vec[0]);
527     }
528 };
529 
530 /*!
531  * \brief Specialized inserter class for vectors of int data.
532  */
533 template <typename T>
534 class rpcbasic_inserter<T, std::vector<int>>
535     : public virtual rpcinserter_base<T, std::vector<int>>
536 {
537 public:
rpcbasic_inserter(T * source,std::vector<int> (T::* func)()const)538     rpcbasic_inserter(T* source, std::vector<int> (T::*func)() const)
539         : rpcinserter_base<T, std::vector<int>>(source, func)
540     {
541         ;
542     }
543 
rpcbasic_inserter(T * source,std::vector<int> (T::* func)())544     rpcbasic_inserter(T* source, std::vector<int> (T::*func)())
545         : rpcinserter_base<T, std::vector<int>>(source, func)
546     {
547         ;
548     }
549 
retrieve()550     pmt::pmt_t retrieve()
551     {
552         std::vector<int> vec((rpcinserter_base<T, std::vector<int>>::_source
553                                   ->*rpcinserter_base<T, std::vector<int>>::_func)());
554         return pmt::init_s32vector(vec.size(), &vec[0]);
555     }
556 };
557 
558 /*!
559  * \brief Specialized inserter class for vectors of int64_t data.
560  */
561 template <typename T>
562 class rpcbasic_inserter<T, std::vector<int64_t>>
563     : public virtual rpcinserter_base<T, std::vector<int64_t>>
564 {
565 public:
rpcbasic_inserter(T * source,std::vector<int64_t> (T::* func)()const)566     rpcbasic_inserter(T* source, std::vector<int64_t> (T::*func)() const)
567         : rpcinserter_base<T, std::vector<int64_t>>(source, func)
568     {
569         ;
570     }
571 
rpcbasic_inserter(T * source,std::vector<int64_t> (T::* func)())572     rpcbasic_inserter(T* source, std::vector<int64_t> (T::*func)())
573         : rpcinserter_base<T, std::vector<int64_t>>(source, func)
574     {
575         ;
576     }
577 
retrieve()578     pmt::pmt_t retrieve()
579     {
580         std::vector<int64_t> vec(
581             (rpcinserter_base<T, std::vector<int64_t>>::_source
582                  ->*rpcinserter_base<T, std::vector<int64_t>>::_func)());
583         return pmt::init_s64vector(vec.size(), &vec[0]);
584     }
585 };
586 
587 /*!
588  * \brief Specialized inserter class for vectors of complex (float) data.
589  */
590 template <typename T>
591 class rpcbasic_inserter<T, std::vector<std::complex<float>>>
592     : public virtual rpcinserter_base<T, std::vector<std::complex<float>>>
593 {
594 public:
rpcbasic_inserter(T * source,std::vector<std::complex<float>> (T::* func)()const)595     rpcbasic_inserter(T* source, std::vector<std::complex<float>> (T::*func)() const)
596         : rpcinserter_base<T, std::vector<std::complex<float>>>(source, func)
597     {
598         ;
599     }
600 
rpcbasic_inserter(T * source,std::vector<std::complex<float>> (T::* func)())601     rpcbasic_inserter(T* source, std::vector<std::complex<float>> (T::*func)())
602         : rpcinserter_base<T, std::vector<std::complex<float>>>(source, func)
603     {
604         ;
605     }
606 
retrieve()607     pmt::pmt_t retrieve()
608     {
609         std::vector<std::complex<float>> vec(
610             (rpcinserter_base<T, std::vector<std::complex<float>>>::_source
611                  ->*rpcinserter_base<T, std::vector<std::complex<float>>>::_func)());
612         return pmt::init_c32vector(vec.size(), &vec[0]);
613     }
614 };
615 
616 /*!
617  * \brief Specialized inserter class for vectors of float data.
618  */
619 template <typename T>
620 class rpcbasic_inserter<T, std::vector<float>>
621     : public virtual rpcinserter_base<T, std::vector<float>>
622 {
623 public:
rpcbasic_inserter(T * source,std::vector<float> (T::* func)()const)624     rpcbasic_inserter(T* source, std::vector<float> (T::*func)() const)
625         : rpcinserter_base<T, std::vector<float>>(source, func)
626     {
627         ;
628     }
629 
rpcbasic_inserter(T * source,std::vector<float> (T::* func)())630     rpcbasic_inserter(T* source, std::vector<float> (T::*func)())
631         : rpcinserter_base<T, std::vector<float>>(source, func)
632     {
633         ;
634     }
635 
retrieve()636     pmt::pmt_t retrieve()
637     {
638         std::vector<float> vec((rpcinserter_base<T, std::vector<float>>::_source
639                                     ->*rpcinserter_base<T, std::vector<float>>::_func)());
640         return pmt::init_f32vector(vec.size(), &vec[0]);
641     }
642 };
643 
644 /*!
645  * \brief Specialized inserter class for vectors of uint8_t data.
646  */
647 template <typename T>
648 class rpcbasic_inserter<T, std::vector<uint8_t>>
649     : public virtual rpcinserter_base<T, std::vector<uint8_t>>
650 {
651 public:
rpcbasic_inserter(T * source,std::vector<uint8_t> (T::* func)()const)652     rpcbasic_inserter(T* source, std::vector<uint8_t> (T::*func)() const)
653         : rpcinserter_base<T, std::vector<uint8_t>>(source, func)
654     {
655         ;
656     }
657 
rpcbasic_inserter(T * source,std::vector<uint8_t> (T::* func)())658     rpcbasic_inserter(T* source, std::vector<uint8_t> (T::*func)())
659         : rpcinserter_base<T, std::vector<uint8_t>>(source, func)
660     {
661         ;
662     }
663 
retrieve()664     pmt::pmt_t retrieve()
665     {
666         std::vector<uint8_t> vec(
667             (rpcinserter_base<T, std::vector<uint8_t>>::_source
668                  ->*rpcinserter_base<T, std::vector<uint8_t>>::_func)());
669         return pmt::init_u8vector(vec.size(), &vec[0]);
670     }
671 };
672 
673 /*!
674  * \brief Specialized inserter class for complex (float) data.
675  */
676 template <typename T>
677 class rpcbasic_inserter<T, std::complex<float>>
678     : public virtual rpcinserter_base<T, std::complex<float>>
679 {
680 public:
rpcbasic_inserter(T * source,std::complex<float> (T::* func)()const)681     rpcbasic_inserter(T* source, std::complex<float> (T::*func)() const)
682         : rpcinserter_base<T, std::complex<float>>(source, func)
683     {
684         ;
685     }
686 
rpcbasic_inserter(T * source,std::complex<float> (T::* func)())687     rpcbasic_inserter(T* source, std::complex<float> (T::*func)())
688         : rpcinserter_base<T, std::complex<float>>(source, func)
689     {
690         ;
691     }
692 
retrieve()693     pmt::pmt_t retrieve()
694     {
695         std::complex<float> k((rpcinserter_base<T, std::complex<float>>::_source
696                                    ->*rpcinserter_base<T, std::complex<float>>::_func)());
697         return pmt::from_complex(k);
698     }
699 };
700 
701 /*!
702  * \brief Specialized inserter class for complex (double) data.
703  */
704 template <typename T>
705 class rpcbasic_inserter<T, std::complex<double>>
706     : public virtual rpcinserter_base<T, std::complex<double>>
707 {
708 public:
rpcbasic_inserter(T * source,std::complex<double> (T::* func)()const)709     rpcbasic_inserter(T* source, std::complex<double> (T::*func)() const)
710         : rpcinserter_base<T, std::complex<double>>(source, func)
711     {
712         ;
713     }
714 
rpcbasic_inserter(T * source,std::complex<double> (T::* func)())715     rpcbasic_inserter(T* source, std::complex<double> (T::*func)())
716         : rpcinserter_base<T, std::complex<double>>(source, func)
717     {
718         ;
719     }
720 
retrieve()721     pmt::pmt_t retrieve()
722     {
723         std::complex<double> k(
724             (rpcinserter_base<T, std::complex<double>>::_source
725                  ->*rpcinserter_base<T, std::complex<double>>::_func)());
726         return pmt::from_complex(k);
727     }
728 };
729 
730 /*!
731  * \brief Base class for registering a ControlPort function.
732  */
733 template <typename T>
734 struct rpc_register_base {
rpc_register_baserpc_register_base735     rpc_register_base() { count++; }
736 
737 protected:
738     static int count;
739 };
740 
741 /*!
742  * Base class to inherit from and create universal shared pointers.
743  */
744 class rpcbasic_base
745 {
746 public:
rpcbasic_base()747     rpcbasic_base() {}
~rpcbasic_base()748     virtual ~rpcbasic_base(){};
749 };
750 
751 
752 /*********************************************************************
753  *   RPC Register Set Classes
754  ********************************************************************/
755 
756 /*!
757  * \brief Registers a 'set' function to set a parameter over
758  * ControlPort.
759  *
760  * \details
761  *
762  * This class allows us to remotely set a value or parameter of the
763  * block over ControlPort. The set occurs by calling a setter accessor
764  * function of the class, usually set_[variable](), which is passed in
765  * as \p function.
766  *
767  * We can set the (expected) minimum (\p min), maximum (\p max), and
768  * default (\p def) of the variables being set. These values are not
769  * enforced, however, but can be useful for setting up graphs and
770  * other ways of bounding the data.
771  *
772  * This class also allows us to provide information to the user about
773  * the variable being set, such as an appropriate unit (\p units_) as
774  * well as a description (\p desc_) about what the variable does.
775  *
776  * The privilege (\p minpriv_) level is the minimum privilege level a
777  * remote must identify with to be able to call this function.
778  *
779  * We also provide display hints (\p display_), which can be used by
780  * the ControlPort client application to know how to best display or
781  * even print the data. This is a mask of options for variables set in
782  * rpccallbackregister_base.h. The mask is defined by one of the
783  * "DisplayType Plotting Types" and or'd with any of the "DisplayType
784  * Options" features. See "Display Options" in \ref page_ctrlport for
785  * details.
786  */
787 template <typename T, typename Tto>
788 struct rpcbasic_register_set : public rpcbasic_base {
789     /*!
790      * \brief Adds the ability to set the variable over ControlPort.
791      *
792      * \details
793      *
794      * This constructor is specifically for gr::block's to use to add
795      * settable variables to ControlPort. Generally meant to be used
796      * in gr::block::setup_rpc.
797      *
798      * Uses the block's alias to create the ControlPort interface. This
799      * alias is cross-referenced by the global_block_registry (static
800      * variable of type gr::block_registry) to get the pointer to the
801      * block.
802      *
803      * \param block_alias  Block's alias; use alias() to get it from the block.
804      * \param functionbase The name of the function that we'll access over ControlPort
805      * \param function     A function pointer to the real function accessed when called
806      *                     something like: &[block class]\::set_[variable]()
807      * \param min          Expected minimum value the parameter can hold
808      * \param max          Expected maximum value the parameter can hold
809      * \param def          Expected default value the parameter can hold
810      * \param units_       A string to describe what units to represent the variable with
811      * \param desc_        A string to describing the variable.
812      * \param minpriv_     The required minimum privilege level
813      * \param display_     The display mask
814      */
815     rpcbasic_register_set(const std::string& block_alias,
816                           const char* functionbase,
817                           void (T::*function)(Tto),
818                           const pmt::pmt_t& min,
819                           const pmt::pmt_t& max,
820                           const pmt::pmt_t& def,
821                           const char* units_ = "",
822                           const char* desc_ = "",
823                           priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
824                           DisplayType display_ = DISPNULL)
825     {
826         d_min = min;
827         d_max = max;
828         d_def = def;
829         d_units = units_;
830         d_desc = desc_;
831         d_minpriv = minpriv_;
832         d_display = display_;
833         d_object = dynamic_cast<T*>(
834             global_block_registry.block_lookup(pmt::intern(block_alias)).get());
835 #ifdef GR_RPCSERVER_ENABLED
836         callbackregister_base::configureCallback_t extractor(
837             new rpcbasic_extractor<T, Tto>(d_object, function),
838             minpriv_,
839             std::string(units_),
840             display_,
841             std::string(desc_),
842             min,
843             max,
844             def);
845         std::ostringstream oss(std::ostringstream::out);
846         oss << block_alias << "::" << functionbase;
847         d_id = oss.str();
848         // std::cerr << "REGISTERING SET: " << d_id << "  " << desc_ << std::endl;
849         rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor);
850 #endif
851     }
852 
853     /*!
854      * \brief Adds the ability to set the variable over ControlPort.
855      *
856      * \details
857      *
858      * Allows us to add non gr::block related objects to
859      * ControlPort. Instead of using the block's alias, we give it a \p
860      * name and the actual pointer to the object as \p obj. We just need
861      * to make sure that the pointer to this object is always valid.
862      *
863      * \param name         Name of the object being set up for ControlPort access
864      * \param functionbase The name of the function that we'll access over ControlPort
865      * \param obj          A pointer to the object itself
866      * \param function     A function pointer to the real function accessed when called
867      *                     something like: &[block class]\::set_[variable]()
868      * \param min          Expected minimum value the parameter can hold
869      * \param max          Expected maximum value the parameter can hold
870      * \param def          Expected default value the parameter can hold
871      * \param units_       A string to describe what units to represent the variable with
872      * \param desc_        A string to describing the variable.
873      * \param minpriv_     The required minimum privilege level
874      * \param display_     The display mask
875      */
876     rpcbasic_register_set(const std::string& name,
877                           const char* functionbase,
878                           T* obj,
879                           void (T::*function)(Tto),
880                           const pmt::pmt_t& min,
881                           const pmt::pmt_t& max,
882                           const pmt::pmt_t& def,
883                           const char* units_ = "",
884                           const char* desc_ = "",
885                           priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
886                           DisplayType display_ = DISPNULL)
887     {
888         d_min = min;
889         d_max = max;
890         d_def = def;
891         d_units = units_;
892         d_desc = desc_;
893         d_minpriv = minpriv_;
894         d_display = display_;
895         d_object = obj;
896 #ifdef GR_RPCSERVER_ENABLED
897         callbackregister_base::configureCallback_t extractor(
898             new rpcbasic_extractor<T, Tto>(d_object, function),
899             minpriv_,
900             std::string(units_),
901             display_,
902             std::string(desc_),
903             min,
904             max,
905             def);
906         std::ostringstream oss(std::ostringstream::out);
907         oss << name << "::" << functionbase;
908         d_id = oss.str();
909         // std::cerr << "REGISTERING SET: " << d_id << "  " << desc_ << std::endl;
910         rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor);
911 #endif
912     }
913 
~rpcbasic_register_setrpcbasic_register_set914     ~rpcbasic_register_set()
915     {
916 #ifdef GR_RPCSERVER_ENABLED
917         rpcmanager::get()->i()->unregisterConfigureCallback(d_id);
918 #endif
919     }
920 
921 
minrpcbasic_register_set922     pmt::pmt_t min() const { return d_min; }
maxrpcbasic_register_set923     pmt::pmt_t max() const { return d_max; }
defrpcbasic_register_set924     pmt::pmt_t def() const { return d_def; }
unitsrpcbasic_register_set925     std::string units() const { return d_units; }
descriptionrpcbasic_register_set926     std::string description() const { return d_desc; }
privilege_levelrpcbasic_register_set927     priv_lvl_t privilege_level() const { return d_minpriv; }
default_displayrpcbasic_register_set928     DisplayType default_display() const { return d_display; }
929 
set_minrpcbasic_register_set930     void set_min(pmt::pmt_t p) { d_min = p; }
set_maxrpcbasic_register_set931     void set_max(pmt::pmt_t p) { d_max = p; }
set_defrpcbasic_register_set932     void set_def(pmt::pmt_t p) { d_def = p; }
unitsrpcbasic_register_set933     void units(std::string u) { d_units = u; }
descriptionrpcbasic_register_set934     void description(std::string d) { d_desc = d; }
privilege_levelrpcbasic_register_set935     void privilege_level(priv_lvl_t p) { d_minpriv = p; }
default_displayrpcbasic_register_set936     void default_display(DisplayType d) { d_display = d; }
937 
938 private:
939     std::string d_id;
940     pmt::pmt_t d_min, d_max, d_def;
941     std::string d_units, d_desc;
942     priv_lvl_t d_minpriv;
943     DisplayType d_display;
944     T* d_object;
945 };
946 
947 
948 /*********************************************************************
949  *   RPC Register Trigger Classes
950  ********************************************************************/
951 
952 /*!
953  * \brief Registers a 'trigger' function to trigger an action over
954  * ControlPort.
955  *
956  * \details
957  *
958  * This class allows us to set up triggered events or function calls
959  * over ControlPort. When used from a ControlPort client, the \p
960  * function established here will be activated. Generally, this is
961  * meant to enable some kind of trigger or action that a block or
962  * object will perform, such as a reset, start, stop, etc.
963  *
964  * Simpler than the rpcbasic_register_set class, the constructor here
965  * only takes a few parameters, mostly because there is not actual
966  * variable associated with these function calls. It takes in the
967  * information to set up the pointer to the object that has the \p
968  * function, a ControlPort name (\p functionbase) for the triggered
969  * action, a description (\p desc_), and a privilege level (\p
970  * minpriv_).
971  */
972 template <typename T>
973 struct rpcbasic_register_trigger : public rpcbasic_base {
974     /*!
975      * \brief Adds the ability to trigger a function over ControlPort.
976      *
977      * \details
978      *
979      * This constructor is specifically for gr::block's to use to add
980      * trigger functions to ControlPort. Generally meant to be used
981      * in gr::block::setup_rpc.
982      *
983      * Uses the block's alias to create the ControlPort interface. This
984      * alias is cross-referenced by the global_block_registry (static
985      * variable of type gr::block_registry) to get the pointer to the
986      * block.
987      *
988      * \param block_alias  Block's alias; use alias() to get it from the block.
989      * \param functionbase The name of the function that we'll access over ControlPort
990      * \param function     A function pointer to the real function accessed when called
991      *                     something like: &[block class]\::set_[variable]
992      * \param desc_        A string to describing the variable.
993      * \param minpriv_     The required minimum privilege level
994      */
995     rpcbasic_register_trigger(const std::string& block_alias,
996                               const char* functionbase,
997                               void (T::*function)(),
998                               const char* desc_ = "",
999                               priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN)
1000     {
1001         d_desc = desc_;
1002         d_minpriv = minpriv_;
1003         d_object = dynamic_cast<T*>(
1004             global_block_registry.block_lookup(pmt::intern(block_alias)).get());
1005 #ifdef GR_RPCSERVER_ENABLED
1006         callbackregister_base::configureCallback_t extractor(
1007             new rpcbasic_extractor<T, void>(d_object, function),
1008             minpriv_,
1009             std::string(desc_));
1010         std::ostringstream oss(std::ostringstream::out);
1011         oss << block_alias << "::" << functionbase;
1012         d_id = oss.str();
1013         // std::cerr << "REGISTERING TRIGGER: " << d_id << "  " << desc_ << std::endl;
1014         rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor);
1015 #endif
1016     }
1017 
1018     /*!
1019      * \brief Adds the ability to trigger a function over ControlPort.
1020      *
1021      * \details
1022      *
1023      * Allows us to add non gr::block related objects to
1024      * ControlPort. Instead of using the block's alias, we give it a \p
1025      * name and the actual pointer to the object as \p obj. We just need
1026      * to make sure that the pointer to this object is always valid.
1027      *
1028      * \param name         Name of the object being set up for ControlPort access
1029      * \param functionbase The name of the function that we'll access over ControlPort
1030      * \param obj          A pointer to the object itself
1031      * \param function     A function pointer to the real function accessed when called
1032      *                     something like: &[block class]\::set_[variable]
1033      * \param desc_        A string to describing the variable.
1034      * \param minpriv_     The required minimum privilege level
1035      */
1036     rpcbasic_register_trigger(const std::string& name,
1037                               const char* functionbase,
1038                               T* obj,
1039                               void (T::*function)(),
1040                               const char* desc_ = "",
1041                               priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN)
1042     {
1043         d_desc = desc_;
1044         d_minpriv = minpriv_;
1045         d_object = obj;
1046 #ifdef GR_RPCSERVER_ENABLED
1047         callbackregister_base::configureCallback_t extractor(
1048             new rpcbasic_extractor<T, void>(d_object, function),
1049             minpriv_,
1050             std::string(desc_));
1051         std::ostringstream oss(std::ostringstream::out);
1052         oss << name << "::" << functionbase;
1053         d_id = oss.str();
1054         // std::cerr << "REGISTERING TRIGGER: " << d_id << "  " << desc_ << std::endl;
1055         rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor);
1056 #endif
1057     }
1058 
~rpcbasic_register_triggerrpcbasic_register_trigger1059     ~rpcbasic_register_trigger()
1060     {
1061 #ifdef GR_RPCSERVER_ENABLED
1062         rpcmanager::get()->i()->unregisterConfigureCallback(d_id);
1063 #endif
1064     }
1065 
1066 
descriptionrpcbasic_register_trigger1067     std::string description() const { return d_desc; }
privilege_levelrpcbasic_register_trigger1068     priv_lvl_t privilege_level() const { return d_minpriv; }
1069 
descriptionrpcbasic_register_trigger1070     void description(std::string d) { d_desc = d; }
privilege_levelrpcbasic_register_trigger1071     void privilege_level(priv_lvl_t p) { d_minpriv = p; }
1072 
1073 private:
1074     std::string d_id;
1075     std::string d_desc;
1076     priv_lvl_t d_minpriv;
1077     T* d_object;
1078 };
1079 
1080 
1081 /*********************************************************************
1082  *   RPC Register Get Classes
1083  ********************************************************************/
1084 
1085 /*!
1086  * \brief Registers a 'get' function to get a parameter over
1087  * ControlPort.
1088  *
1089  * \details
1090  *
1091  * This class allows us to remotely get a value or parameter of the
1092  * block over ControlPort. The get occurs by calling a getter accessor
1093  * function of the class, usually [variable](), which is passed in
1094  * as \p function.
1095  *
1096  * We can set the (expected) minimum (\p min), maximum (\p max), and
1097  * default (\p def) of the variables we will get. These values are not
1098  * enforced, however, but can be useful for setting up graphs and
1099  * other ways of bounding the data.
1100  *
1101  * This class also allows us to provide information to the user about
1102  * the variable, such as an appropriate unit (\p units_) as well as a
1103  * description (\p desc_) about what the variable does.
1104  *
1105  * The privilege (\p minpriv_) level is the minimum privilege level a
1106  * remote must identify with to be able to call this function.
1107  *
1108  * We also provide display hints (\p display_), which can be used by
1109  * the ControlPort client application to know how to best display or
1110  * even print the data. This is a mask of options for variables set in
1111  * rpccallbackregister_base.h. The mask is defined by one of the
1112  * "DisplayType Plotting Types" and or'd with any of the "DisplayType
1113  * Options" features. See "Display Options" in \ref page_ctrlport for
1114  * details.
1115  */
1116 template <typename T, typename Tfrom>
1117 class rpcbasic_register_get : public rpcbasic_base
1118 {
1119 public:
1120     /*!
1121      * \brief Adds the ability to get the variable over ControlPort.
1122      *
1123      * \details
1124      *
1125      * This constructor is specifically for gr::block's to use to add
1126      * gettable variables to ControlPort. Generally meant to be used
1127      * in gr::block::setup_rpc.
1128      *
1129      * Uses the block's alias to create the ControlPort interface. This
1130      * alias is cross-referenced by the global_block_registry (static
1131      * variable of type gr::block_registry) to get the pointer to the
1132      * block.
1133      *
1134      * \param block_alias  Block's alias; use alias() to get it from the block.
1135      * \param functionbase The name of the function that we'll access over ControlPort
1136      * \param function     A function pointer to the real function accessed when called
1137      *                     something like: &[block class]\::[variable]()
1138      * \param min          Expected minimum value the parameter can hold
1139      * \param max          Expected maximum value the parameter can hold
1140      * \param def          Expected default value the parameter can hold
1141      * \param units_       A string to describe what units to represent the variable with
1142      * \param desc_        A string to describing the variable.
1143      * \param minpriv_     The required minimum privilege level
1144      * \param display_     The display mask
1145      */
1146     rpcbasic_register_get(const std::string& block_alias,
1147                           const char* functionbase,
1148                           Tfrom (T::*function)(),
1149                           const pmt::pmt_t& min,
1150                           const pmt::pmt_t& max,
1151                           const pmt::pmt_t& def,
1152                           const char* units_ = "",
1153                           const char* desc_ = "",
1154                           priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
1155                           DisplayType display_ = DISPNULL)
1156     {
1157         d_min = min;
1158         d_max = max;
1159         d_def = def;
1160         d_units = units_;
1161         d_desc = desc_;
1162         d_minpriv = minpriv_;
1163         d_display = display_;
1164         d_object = dynamic_cast<T*>(
1165             global_block_registry.block_lookup(pmt::intern(block_alias)).get());
1166 #ifdef GR_RPCSERVER_ENABLED
1167         callbackregister_base::queryCallback_t inserter(
1168             new rpcbasic_inserter<T, Tfrom>(d_object, function),
1169             minpriv_,
1170             std::string(units_),
1171             display_,
1172             std::string(desc_),
1173             min,
1174             max,
1175             def);
1176         std::ostringstream oss(std::ostringstream::out);
1177         oss << block_alias << "::" << functionbase;
1178         d_id = oss.str();
1179         // std::cerr << "REGISTERING GET: " << d_id << "  " << desc_ << std::endl;
1180         rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
1181 #endif
1182     }
1183 
1184 
1185     /*!
1186      * \brief Same as rpcbasic_register_get::rpcbasic_register_get that allows using
1187      * '[variable]() const' getter functions.
1188      */
1189     rpcbasic_register_get(const std::string& block_alias,
1190                           const char* functionbase,
1191                           Tfrom (T::*function)() const,
1192                           const pmt::pmt_t& min,
1193                           const pmt::pmt_t& max,
1194                           const pmt::pmt_t& def,
1195                           const char* units_ = "",
1196                           const char* desc_ = "",
1197                           priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
1198                           DisplayType display_ = DISPNULL)
1199     {
1200         d_min = min;
1201         d_max = max;
1202         d_def = def;
1203         d_units = units_;
1204         d_desc = desc_;
1205         d_minpriv = minpriv_;
1206         d_display = display_;
1207         d_object = dynamic_cast<T*>(
1208             global_block_registry.block_lookup(pmt::intern(block_alias)).get());
1209 #ifdef GR_RPCSERVER_ENABLED
1210         callbackregister_base::queryCallback_t inserter(
1211             new rpcbasic_inserter<T, Tfrom>(d_object, (Tfrom(T::*)())function),
1212             minpriv_,
1213             std::string(units_),
1214             display_,
1215             std::string(desc_),
1216             min,
1217             max,
1218             def);
1219         std::ostringstream oss(std::ostringstream::out);
1220         oss << block_alias << "::" << functionbase;
1221         d_id = oss.str();
1222         // std::cerr << "REGISTERING GET CONST: " << d_id << "   " << desc_ << "   " <<
1223         // display_ << std::endl;
1224         rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
1225 #endif
1226     }
1227 
1228 
1229     /*!
1230      * \brief Adds the ability to get the variable over ControlPort.
1231      *
1232      * \details
1233      *
1234      * Allows us to add non gr::block related objects to
1235      * ControlPort. Instead of using the block's alias, we give it a \p
1236      * name and the actual pointer to the object as \p obj. We just need
1237      * to make sure that the pointer to this object is always valid.
1238      *
1239      * \param name         Name of the object being set up for ControlPort access
1240      * \param functionbase The name of the function that we'll access over ControlPort
1241      * \param obj          A pointer to the object itself
1242      * \param function     A function pointer to the real function accessed when called
1243      *                     something like: &[block class]\::set_[variable]()
1244      * \param min          Expected minimum value the parameter can hold
1245      * \param max          Expected maximum value the parameter can hold
1246      * \param def          Expected default value the parameter can hold
1247      * \param units_       A string to describe what units to represent the variable with
1248      * \param desc_        A string to describing the variable.
1249      * \param minpriv_     The required minimum privilege level
1250      * \param display_     The display mask
1251      */
1252     rpcbasic_register_get(const std::string& name,
1253                           const char* functionbase,
1254                           T* obj,
1255                           Tfrom (T::*function)(),
1256                           const pmt::pmt_t& min,
1257                           const pmt::pmt_t& max,
1258                           const pmt::pmt_t& def,
1259                           const char* units_ = "",
1260                           const char* desc_ = "",
1261                           priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
1262                           DisplayType display_ = DISPNULL)
1263     {
1264         d_min = min;
1265         d_max = max;
1266         d_def = def;
1267         d_units = units_;
1268         d_desc = desc_;
1269         d_minpriv = minpriv_;
1270         d_display = display_;
1271         d_object = obj;
1272 #ifdef GR_RPCSERVER_ENABLED
1273         callbackregister_base::queryCallback_t inserter(
1274             new rpcbasic_inserter<T, Tfrom>(d_object, function),
1275             minpriv_,
1276             std::string(units_),
1277             display_,
1278             std::string(desc_),
1279             min,
1280             max,
1281             def);
1282         std::ostringstream oss(std::ostringstream::out);
1283         oss << name << "::" << functionbase;
1284         d_id = oss.str();
1285         // std::cerr << "REGISTERING GET: " << d_id << "  " << desc_ << std::endl;
1286         rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
1287 #endif
1288     }
1289 
1290 
1291     /*!
1292      * \brief Same as above that allows using '[variable]() const'
1293      * getter functions.
1294      */
1295     rpcbasic_register_get(const std::string& name,
1296                           const char* functionbase,
1297                           T* obj,
1298                           Tfrom (T::*function)() const,
1299                           const pmt::pmt_t& min,
1300                           const pmt::pmt_t& max,
1301                           const pmt::pmt_t& def,
1302                           const char* units_ = "",
1303                           const char* desc_ = "",
1304                           priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
1305                           DisplayType display_ = DISPNULL)
1306     {
1307         d_min = min;
1308         d_max = max;
1309         d_def = def;
1310         d_units = units_;
1311         d_desc = desc_;
1312         d_minpriv = minpriv_;
1313         d_display = display_;
1314         d_object = obj;
1315 #ifdef GR_RPCSERVER_ENABLED
1316         callbackregister_base::queryCallback_t inserter(
1317             new rpcbasic_inserter<T, Tfrom>(d_object, (Tfrom(T::*)())function),
1318             minpriv_,
1319             std::string(units_),
1320             display_,
1321             std::string(desc_),
1322             min,
1323             max,
1324             def);
1325         std::ostringstream oss(std::ostringstream::out);
1326         oss << name << "::" << functionbase;
1327         d_id = oss.str();
1328         // std::cerr << "REGISTERING GET CONST: " << d_id << "   " << desc_ << "   " <<
1329         // display_ << std::endl;
1330         rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
1331 #endif
1332     }
1333 
~rpcbasic_register_get()1334     ~rpcbasic_register_get()
1335     {
1336 #ifdef GR_RPCSERVER_ENABLED
1337         rpcmanager::get()->i()->unregisterQueryCallback(d_id);
1338 #endif
1339     }
1340 
min()1341     pmt::pmt_t min() const { return d_min; }
max()1342     pmt::pmt_t max() const { return d_max; }
def()1343     pmt::pmt_t def() const { return d_def; }
units()1344     std::string units() const { return d_units; }
description()1345     std::string description() const { return d_desc; }
privilege_level()1346     priv_lvl_t privilege_level() const { return d_minpriv; }
default_display()1347     DisplayType default_display() const { return d_display; }
1348 
set_min(pmt::pmt_t p)1349     void set_min(pmt::pmt_t p) { d_min = p; }
set_max(pmt::pmt_t p)1350     void set_max(pmt::pmt_t p) { d_max = p; }
set_def(pmt::pmt_t p)1351     void set_def(pmt::pmt_t p) { d_def = p; }
units(std::string u)1352     void units(std::string u) { d_units = u; }
description(std::string d)1353     void description(std::string d) { d_desc = d; }
privilege_level(priv_lvl_t p)1354     void privilege_level(priv_lvl_t p) { d_minpriv = p; }
default_display(DisplayType d)1355     void default_display(DisplayType d) { d_display = d; }
1356 
1357 private:
1358     std::string d_id;
1359     pmt::pmt_t d_min, d_max, d_def;
1360     std::string d_units, d_desc;
1361     priv_lvl_t d_minpriv;
1362     DisplayType d_display;
1363     T* d_object;
1364 };
1365 
1366 
1367 /*********************************************************************
1368  *   RPC Register Variable Classes
1369  ********************************************************************/
1370 
1371 /*!
1372  * \brief Registers a read-only function to get a parameter over ControlPort.
1373  *
1374  * \details
1375  *
1376  * This class allows us to remotely get a value or parameter of the
1377  * block over ControlPort. Unlike the rpcbasic_register_get class,
1378  * this version is passed the variable directly and establishes a
1379  * getter for us, so there is no need to have a getter function
1380  * already in the object.
1381  *
1382  * This version is for read-only get access.
1383  *
1384  * We can set the (expected) minimum (\p min), maximum (\p max), and
1385  * default (\p def) of the variables we will get. These values are not
1386  * enforced, however, but can be useful for setting up graphs and
1387  * other ways of bounding the data.
1388  *
1389  * This class also allows us to provide information to the user about
1390  * the variable, such as an appropriate unit (\p units_) as well as a
1391  * description (\p desc_) about what the variable does.
1392  *
1393  * The privilege (\p minpriv_) level is the minimum privilege level a
1394  * remote must identify with to be able to call this function.
1395  *
1396  * We also provide display hints (\p display_), which can be used by
1397  * the ControlPort client application to know how to best display or
1398  * even print the data. This is a mask of options for variables set in
1399  * rpccallbackregister_base.h. The mask is defined by one of the
1400  * "DisplayType Plotting Types" and or'd with any of the "DisplayType
1401  * Options" features. See "Display Options" in \ref page_ctrlport for
1402  * details.
1403  */
1404 template <typename Tfrom>
1405 class rpcbasic_register_variable : public rpcbasic_base
1406 {
1407 protected:
1408     rpcbasic_register_get<rpcbasic_register_variable<Tfrom>, Tfrom> d_rpc_reg;
1409     Tfrom* d_variable;
get()1410     Tfrom get() { return *d_variable; }
1411 
1412 public:
setptr(Tfrom * _variable)1413     void setptr(Tfrom* _variable)
1414     {
1415         rpcbasic_register_variable<Tfrom>::d_variable = _variable;
1416     }
1417 
1418     /*! Empty constructor which should never be called but needs to
1419      * exist for ues in varous STL data structures
1420      */
rpcbasic_register_variable()1421     rpcbasic_register_variable()
1422         : d_rpc_reg("FAIL",
1423                     "FAIL",
1424                     this,
1425                     &rpcbasic_register_variable::get,
1426                     pmt::PMT_NIL,
1427                     pmt::PMT_NIL,
1428                     pmt::PMT_NIL,
1429                     DISPNULL,
1430                     "FAIL",
1431                     "FAIL",
1432                     RPC_PRIVLVL_MIN),
1433           d_variable(NULL)
1434     {
1435         throw std::runtime_error(
1436             "ERROR: rpcbasic_register_variable called with no args. If this happens, "
1437             "someone has tried to use rpcbasic_register_variable incorrectly.");
1438     };
1439 
1440     /*!
1441      * \brief Adds the ability to get the variable over ControlPort.
1442      *
1443      * \details
1444      *
1445      * Creates a new getter accessor function to read \p variable.
1446      *
1447      * \param namebase     Name of the object being set up for ControlPort access
1448      * \param functionbase The name of the function that we'll access over ControlPort
1449      * \param variable     A pointer to the variable, possibly as a member of a class
1450      * \param min          Expected minimum value the parameter can hold
1451      * \param max          Expected maximum value the parameter can hold
1452      * \param def          Expected default value the parameter can hold
1453      * \param units_       A string to describe what units to represent the variable with
1454      * \param desc_        A string to describing the variable.
1455      * \param minpriv_     The required minimum privilege level
1456      * \param display_     The display mask
1457      */
1458     rpcbasic_register_variable(const std::string& namebase,
1459                                const char* functionbase,
1460                                Tfrom* variable,
1461                                const pmt::pmt_t& min,
1462                                const pmt::pmt_t& max,
1463                                const pmt::pmt_t& def,
1464                                const char* units_ = "",
1465                                const char* desc_ = "",
1466                                priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
1467                                DisplayType display_ = DISPNULL)
1468         : d_rpc_reg(namebase,
1469                     functionbase,
1470                     this,
1471                     &rpcbasic_register_variable::get,
1472                     min,
1473                     max,
1474                     def,
1475                     units_,
1476                     desc_,
1477                     minpriv_,
1478                     display_),
1479           d_variable(variable)
1480     {
1481         // std::cerr << "REGISTERING VAR: " << " " << desc_ << std::endl;
1482     }
1483 };
1484 
1485 
1486 /*!
1487  * \brief Registers a read/write function to get and set a parameter
1488  * over ControlPort.
1489  *
1490  * \details
1491  *
1492  * This class allows us to remotely get and/or set a value or
1493  * parameter of the block over ControlPort. Unlike the
1494  * rpcbasic_register_get class, this version is passed the variable
1495  * directly and establishes a getter for us, so there is no need to
1496  * have a getter function already in the object.
1497  *
1498  * This version establishes both get and set functions and so provides
1499  * read/write access to the variable.
1500  *
1501  * We can set the (expected) minimum (\p min), maximum (\p max), and
1502  * default (\p def) of the variables we will get. These values are not
1503  * enforced, however, but can be useful for setting up graphs and
1504  * other ways of bounding the data.
1505  *
1506  * This class also allows us to provide information to the user about
1507  * the variable, such as an appropriate unit (\p units_) as well as a
1508  * description (\p desc_) about what the variable does.
1509  *
1510  * The privilege (\p minpriv_) level is the minimum privilege level a
1511  * remote must identify with to be able to call this function.
1512  *
1513  * We also provide display hints (\p display_), which can be used by
1514  * the ControlPort client application to know how to best display or
1515  * even print the data. This is a mask of options for variables set in
1516  * rpccallbackregister_base.h. The mask is defined by one of the
1517  * "DisplayType Plotting Types" and or'd with any of the "DisplayType
1518  * Options" features. See "Display Options" in \ref page_ctrlport for
1519  * details.
1520  */
1521 template <typename Tfrom>
1522 class rpcbasic_register_variable_rw : public rpcbasic_register_variable<Tfrom>
1523 {
1524 private:
1525     rpcbasic_register_set<rpcbasic_register_variable_rw<Tfrom>, Tfrom> d_rpc_regset;
1526 
1527 public:
1528     /*! Empty constructor which should never be called but needs to
1529      *  exist for ues in varous STL data structures.
1530      */
rpcbasic_register_variable_rw()1531     rpcbasic_register_variable_rw()
1532         : d_rpc_regset("FAIL",
1533                        "FAIL",
1534                        this,
1535                        &rpcbasic_register_variable<Tfrom>::get,
1536                        pmt::PMT_NIL,
1537                        pmt::PMT_NIL,
1538                        pmt::PMT_NIL,
1539                        DISPNULL,
1540                        "FAIL",
1541                        "FAIL",
1542                        RPC_PRIVLVL_MIN)
1543     {
1544         throw std::runtime_error(
1545             "ERROR: rpcbasic_register_variable_rw called with no args. if this happens "
1546             "someone used rpcbasic_register_variable_rw incorrectly.\n");
1547     };
1548 
set(Tfrom _variable)1549     void set(Tfrom _variable)
1550     {
1551         *(rpcbasic_register_variable<Tfrom>::d_variable) = _variable;
1552     }
1553 
1554     /*!
1555      * \brief Adds the ability to set and get the variable over ControlPort.
1556      *
1557      * \details
1558      *
1559      * Creates new getter and setter accessor functions to read and write \p variable.
1560      *
1561      * \param namebase     Name of the object being set up for ControlPort access
1562      * \param functionbase The name of the function that we'll access over ControlPort
1563      * \param variable     A pointer to the variable, possibly as a member of a class
1564      * \param min          Expected minimum value the parameter can hold
1565      * \param max          Expected maximum value the parameter can hold
1566      * \param def          Expected default value the parameter can hold
1567      * \param units_       A string to describe what units to represent the variable with
1568      * \param desc_        A string to describing the variable.
1569      * \param minpriv      The required minimum privilege level
1570      * \param display_     The display mask
1571      */
1572     rpcbasic_register_variable_rw(const std::string& namebase,
1573                                   const char* functionbase,
1574                                   Tfrom* variable,
1575                                   const pmt::pmt_t& min,
1576                                   const pmt::pmt_t& max,
1577                                   const pmt::pmt_t& def,
1578                                   const char* units_ = "",
1579                                   const char* desc_ = "",
1580                                   priv_lvl_t minpriv = RPC_PRIVLVL_MIN,
1581                                   DisplayType display_ = DISPNULL)
1582         : rpcbasic_register_variable<Tfrom>(
1583               namebase, functionbase, variable, min, max, def, units_, desc_),
1584           d_rpc_regset(namebase,
1585                        functionbase,
1586                        this,
1587                        &rpcbasic_register_variable_rw::set,
1588                        min,
1589                        max,
1590                        def,
1591                        units_,
1592                        desc_,
1593                        minpriv,
1594                        display_)
1595     {
1596         // no action
1597     }
1598 };
1599 
1600 
1601 /*!
1602  * \brief Registers a message handler function to post a message to a
1603  * block's handler.
1604  */
1605 template <typename T>
1606 class rpcbasic_register_handler : public rpcbasic_base
1607 {
1608 public:
1609     /*!
1610      * \brief Adds the ability to pass a message over ControlPort.
1611      *
1612      * \details
1613      * This makes any message handler function available over
1614      * ControlPort. Since message handlers always take in a single PMT
1615      * message input, this interface provides a very generic way of
1616      * setting values in a block in a flowgraph.
1617      *
1618      * \param block_alias  Alias of the block
1619      * \param handler      The name of the message port in the block
1620      * \param units_       A string to describe what units to represent the variable with
1621      * \param desc_        A string to describing the variable.
1622      * \param minpriv_     The required minimum privilege level
1623      * \param display_     The display mask
1624      */
1625     rpcbasic_register_handler(const std::string& block_alias,
1626                               const char* handler,
1627                               const char* units_ = "",
1628                               const char* desc_ = "",
1629                               priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
1630                               DisplayType display_ = DISPNULL)
1631     {
1632         d_units = units_;
1633         d_desc = desc_;
1634         d_minpriv = minpriv_;
1635         d_display = display_;
1636         d_object = dynamic_cast<T*>(
1637             global_block_registry.block_lookup(pmt::intern(block_alias)).get());
1638 #ifdef GR_RPCSERVER_ENABLED
1639         callbackregister_base::handlerCallback_t inserter(
1640             new rpcbasic_handler<T>(d_object, handler),
1641             minpriv_,
1642             std::string(units_),
1643             display_,
1644             std::string(desc_),
1645             0,
1646             0,
1647             0);
1648         std::ostringstream oss(std::ostringstream::out);
1649         oss << block_alias << "::" << handler;
1650         d_id = oss.str();
1651         // std::cerr << "REGISTERING GET: " << d_id << "  " << desc_ << std::endl;
1652         rpcmanager::get()->i()->registerHandlerCallback(d_id, inserter);
1653 #endif
1654     }
1655 
~rpcbasic_register_handler()1656     ~rpcbasic_register_handler()
1657     {
1658 #ifdef GR_RPCSERVER_ENABLED
1659         rpcmanager::get()->i()->unregisterHandlerCallback(d_id);
1660 #endif
1661     }
1662 
units()1663     std::string units() const { return d_units; }
description()1664     std::string description() const { return d_desc; }
privilege_level()1665     priv_lvl_t privilege_level() const { return d_minpriv; }
default_display()1666     DisplayType default_display() const { return d_display; }
1667 
units(std::string u)1668     void units(std::string u) { d_units = u; }
description(std::string d)1669     void description(std::string d) { d_desc = d; }
privilege_level(priv_lvl_t p)1670     void privilege_level(priv_lvl_t p) { d_minpriv = p; }
default_display(DisplayType d)1671     void default_display(DisplayType d) { d_display = d; }
1672 
1673 private:
1674     std::string d_id;
1675     std::string d_units, d_desc;
1676     priv_lvl_t d_minpriv;
1677     DisplayType d_display;
1678     T* d_object;
1679 };
1680 
1681 
1682 #endif
1683