diff --git a/CMakeLists.txt b/CMakeLists.txt index 74c54f5..b4bb535 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) # Find GNURadio (pmt and runtime are core, always included) -find_package(Gnuradio "3.8" REQUIRED COMPONENTS blocks fft filter) +find_package(Gnuradio "3.9" REQUIRED COMPONENTS blocks fft filter) # Set the version information here set(VERSION_MAJOR 0) @@ -188,20 +188,11 @@ find_package(Doxygen) ########## find_package(PythonLibs 3) -find_package(SWIG) - -if(SWIG_FOUND) - message(STATUS "Minimum SWIG version required is 1.3.31") - set(SWIG_VERSION_CHECK FALSE) - if("${SWIG_VERSION}" VERSION_GREATER "1.3.30") - set(SWIG_VERSION_CHECK TRUE) - endif() -endif(SWIG_FOUND) +find_package(pybind11) GR_REGISTER_COMPONENT("Python support" ENABLE_PYTHON PYTHONLIBS_FOUND - SWIG_FOUND - SWIG_VERSION_CHECK + pybind11_FOUND ) ######################################################################## @@ -269,7 +260,6 @@ add_custom_target(uninstall add_subdirectory(include/osmosdr) add_subdirectory(lib) if(ENABLE_PYTHON) - add_subdirectory(swig) add_subdirectory(python) add_subdirectory(grc) add_subdirectory(apps) diff --git a/docs/doxygen/pydoc_macros.h b/docs/doxygen/pydoc_macros.h new file mode 100644 index 0000000..98bf7cd --- /dev/null +++ b/docs/doxygen/pydoc_macros.h @@ -0,0 +1,19 @@ +#ifndef PYDOC_MACROS_H +#define PYDOC_MACROS_H + +#define __EXPAND(x) x +#define __COUNT(_1, _2, _3, _4, _5, _6, _7, COUNT, ...) COUNT +#define __VA_SIZE(...) __EXPAND(__COUNT(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1)) +#define __CAT1(a, b) a##b +#define __CAT2(a, b) __CAT1(a, b) +#define __DOC1(n1) __doc_##n1 +#define __DOC2(n1, n2) __doc_##n1##_##n2 +#define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3 +#define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4 +#define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4##_##n5 +#define __DOC6(n1, n2, n3, n4, n5, n6) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6 +#define __DOC7(n1, n2, n3, n4, n5, n6, n7) \ + __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6##_##n7 +#define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__)) + +#endif // PYDOC_MACROS_H \ No newline at end of file diff --git a/docs/doxygen/swig_doc.py b/docs/doxygen/update_pydoc.py similarity index 58% rename from docs/doxygen/swig_doc.py rename to docs/doxygen/update_pydoc.py index e3b308e..e6b4544 100644 --- a/docs/doxygen/swig_doc.py +++ b/docs/doxygen/update_pydoc.py @@ -2,34 +2,22 @@ # Copyright 2010-2012 Free Software Foundation, Inc. # # This file was generated by gr_modtool, a tool from the GNU Radio framework -# This file is a part of gr-osmosdr +# This file is a part of gnuradio # -# 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. +# SPDX-License-Identifier: GPL-3.0-or-later # -# 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. # """ -Creates the swig_doc.i SWIG interface file. -Execute using: python swig_doc.py xml_path outputfilename +Updates the *pydoc_h files for a module +Execute using: python update_pydoc.py xml_path outputfilename -The file instructs SWIG to transfer the doxygen comments into the +The file instructs Pybind11 to transfer the doxygen comments into the python docstrings. """ -from __future__ import unicode_literals -import sys, time +import os, sys, time, glob, re, json +from argparse import ArgumentParser from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile from doxyxml import DoxyOther, base @@ -87,6 +75,7 @@ def utoascii(text): return '' out = text.encode('ascii', 'replace') # swig will require us to replace blackslash with 4 backslashes + # TODO: evaluate what this should be for pybind11 out = out.replace(b'\\', b'\\\\\\\\') out = out.replace(b'"', b'\\"').decode('ascii') return str(out) @@ -115,7 +104,7 @@ def format_params(parameteritems): entry_templ = '%feature("docstring") {name} "{docstring}"' def make_entry(obj, name=None, templ="{description}", description=None, params=[]): """ - Create a docstring entry for a swig interface file. + Create a docstring key/value pair, where the key is the object name. obj - a doxyxml object from which documentation will be extracted. name - the name of the C object (defaults to obj.name()) @@ -126,6 +115,8 @@ def make_entry(obj, name=None, templ="{description}", description=None, params=[ """ if name is None: name=obj.name() + if hasattr(obj,'_parse_data') and hasattr(obj._parse_data,'definition'): + name=obj._parse_data.definition.split(' ')[-1] if "operator " in name: return '' if description is None: @@ -134,56 +125,28 @@ def make_entry(obj, name=None, templ="{description}", description=None, params=[ description += '\n\n' description += utoascii(format_params(params)) docstring = templ.format(description=description) - if not docstring: - return '' - return entry_templ.format( - name=name, - docstring=docstring, - ) - -def make_func_entry(func, name=None, description=None, params=None): - """ - Create a function docstring entry for a swig interface file. - - func - a doxyxml object from which documentation will be extracted. - name - the name of the C object (defaults to func.name()) - description - if this optional variable is set then it's value is - used as the description instead of extracting it from func. - params - a parameter list that overrides using func.params. - """ - #if params is None: - # params = func.params - #params = [prm.declname for prm in params] - #if params: - # sig = "Params: (%s)" % ", ".join(params) - #else: - # sig = "Params: (NONE)" - #templ = "{description}\n\n" + sig - #return make_entry(func, name=name, templ=utoascii(templ), - # description=description) - return make_entry(func, name=name, description=description, params=params) + return {name: docstring} def make_class_entry(klass, description=None, ignored_methods=[], params=None): """ - Create a class docstring for a swig interface file. + Create a class docstring key/value pair. """ if params is None: params = klass.params - output = [] - output.append(make_entry(klass, description=description, params=params)) + output = {} + output.update(make_entry(klass, description=description, params=params)) for func in klass.in_category(DoxyFunction): if func.name() not in ignored_methods: name = klass.name() + '::' + func.name() - output.append(make_func_entry(func, name=name)) - return "\n\n".join(output) + output.update(make_entry(func, name=name)) + return output def make_block_entry(di, block): """ - Create class and function docstrings of a gnuradio block for a - swig interface file. + Create class and function docstrings of a gnuradio block """ descriptions = [] # Get the documentation associated with the class. @@ -208,18 +171,16 @@ def make_block_entry(di, block): super_description = "\n\n".join(descriptions) # Associate the combined description with the class and # the make function. - output = [] - output.append(make_class_entry(block, description=super_description)) - output.append(make_func_entry(make_func, description=super_description, + output = {} + output.update(make_class_entry(block, description=super_description)) + output.update(make_entry(make_func, description=super_description, params=block.params)) - return "\n\n".join(output) + return output def make_block2_entry(di, block): """ - Create class and function docstrings of a new style gnuradio block for a - swig interface file. + Create class and function docstrings of a new style gnuradio block """ - descriptions = [] # For new style blocks all the relevant documentation should be # associated with the 'make' method. class_description = combine_descriptions(block) @@ -228,28 +189,21 @@ def make_block2_entry(di, block): description = class_description + "\n\nConstructor Specific Documentation:\n\n" + make_description # Associate the combined description with the class and # the make function. - output = [] - output.append(make_class_entry( + output = {} + output.update(make_class_entry( block, description=description, ignored_methods=['make'], params=make_func.params)) makename = block.name() + '::make' - output.append(make_func_entry( + output.update(make_entry( make_func, name=makename, description=description, params=make_func.params)) - return "\n\n".join(output) + return output -def make_swig_interface_file(di, swigdocfilename, custom_output=None): +def get_docstrings_dict(di, custom_output=None): - output = [""" -/* - * This file was automatically generated using swig_doc.py. - * - * Any changes to it will be lost next time it is regenerated. - */ -"""] - - if custom_output is not None: - output.append(custom_output) + output = {} + if custom_output: + output.update(custom_output) # Create docstrings for the blocks. blocks = di.in_category(Block) @@ -262,7 +216,7 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None): # Don't want to risk writing to output twice. if make_func.name() not in make_funcs: make_funcs.add(make_func.name()) - output.append(make_block_entry(di, block)) + output.update(make_block_entry(di, block)) except block.ParsingError: sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) raise @@ -274,7 +228,7 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None): # Don't want to risk writing to output twice. if make_func_name not in make_funcs: make_funcs.add(make_func_name) - output.append(make_block2_entry(di, block)) + output.update(make_block2_entry(di, block)) except block.ParsingError: sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) raise @@ -285,7 +239,7 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None): if f.name() not in make_funcs and not f.name().startswith('std::')] for f in funcs: try: - output.append(make_func_entry(f)) + output.update(make_entry(f)) except f.ParsingError: sys.stderr.write('Parsing error for function {0}\n'.format(f.name())) @@ -296,37 +250,97 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None): if k.name() not in block_names and not k.name().startswith('std::')] for k in klasses: try: - output.append(make_class_entry(k)) + output.update(make_class_entry(k)) except k.ParsingError: sys.stderr.write('Parsing error for class {0}\n'.format(k.name())) # Docstrings are not created for anything that is not a function or a class. # If this excludes anything important please add it here. - output = "\n\n".join(output) + return output - swig_doc = open(swigdocfilename, 'w') - swig_doc.write(output) - swig_doc.close() +def sub_docstring_in_pydoc_h(pydoc_files, docstrings_dict, output_dir, filter_str=None): + if filter_str: + docstrings_dict = {k: v for k, v in docstrings_dict.items() if k.startswith(filter_str)} + + with open(os.path.join(output_dir,'docstring_status'),'w') as status_file: + + for pydoc_file in pydoc_files: + if filter_str: + filter_str2 = "::".join((filter_str,os.path.split(pydoc_file)[-1].split('_pydoc_template.h')[0])) + docstrings_dict2 = {k: v for k, v in docstrings_dict.items() if k.startswith(filter_str2)} + else: + docstrings_dict2 = docstrings_dict + + + + file_in = open(pydoc_file,'r').read() + for key, value in docstrings_dict2.items(): + file_in_tmp = file_in + try: + doc_key = key.split("::") + # if 'gr' in doc_key: + # doc_key.remove('gr') + doc_key = '_'.join(doc_key) + regexp = r'(__doc_{} =\sR\"doc\()[^)]*(\)doc\")'.format(doc_key) + regexp = re.compile(regexp, re.MULTILINE) + + (file_in, nsubs) = regexp.subn(r'\1'+value+r'\2', file_in, count=1) + if nsubs == 1: + status_file.write("PASS: " + pydoc_file + "\n") + except KeyboardInterrupt: + raise KeyboardInterrupt + except: # be permissive, TODO log, but just leave the docstring blank + status_file.write("FAIL: " + pydoc_file + "\n") + file_in = file_in_tmp + + output_pathname = os.path.join(output_dir, os.path.basename(pydoc_file).replace('_template.h','.h')) + # FIXME: Remove this debug print + print('output docstrings to {}'.format(output_pathname)) + with open(output_pathname,'w') as file_out: + file_out.write(file_in) + +def copy_docstring_templates(pydoc_files, output_dir): + with open(os.path.join(output_dir,'docstring_status'),'w') as status_file: + for pydoc_file in pydoc_files: + file_in = open(pydoc_file,'r').read() + output_pathname = os.path.join(output_dir, os.path.basename(pydoc_file).replace('_template.h','.h')) + # FIXME: Remove this debug print + print('copy docstrings to {}'.format(output_pathname)) + with open(output_pathname,'w') as file_out: + file_out.write(file_in) + status_file.write("DONE") + +def argParse(): + """Parses commandline args.""" + desc='Scrape the doxygen generated xml for docstrings to insert into python bindings' + parser = ArgumentParser(description=desc) + + parser.add_argument("function", help="Operation to perform on docstrings", choices=["scrape","sub","copy"]) + + parser.add_argument("--xml_path") + parser.add_argument("--bindings_dir") + parser.add_argument("--output_dir") + parser.add_argument("--json_path") + parser.add_argument("--filter", default=None) + + return parser.parse_args() if __name__ == "__main__": # Parse command line options and set up doxyxml. - err_msg = "Execute using: python swig_doc.py xml_path outputfilename" - if len(sys.argv) != 3: - raise Exception(err_msg) - xml_path = sys.argv[1] - swigdocfilename = sys.argv[2] - di = DoxyIndex(xml_path) + args = argParse() + if args.function.lower() == 'scrape': + di = DoxyIndex(args.xml_path) + docstrings_dict = get_docstrings_dict(di) + with open(args.json_path, 'w') as fp: + json.dump(docstrings_dict, fp) + elif args.function.lower() == 'sub': + with open(args.json_path, 'r') as fp: + docstrings_dict = json.load(fp) + pydoc_files = glob.glob(os.path.join(args.bindings_dir,'*_pydoc_template.h')) + sub_docstring_in_pydoc_h(pydoc_files, docstrings_dict, args.output_dir, args.filter) + elif args.function.lower() == 'copy': + pydoc_files = glob.glob(os.path.join(args.bindings_dir,'*_pydoc_template.h')) + copy_docstring_templates(pydoc_files, args.output_dir) - # gnuradio.gr.msq_queue.insert_tail and delete_head create errors unless docstrings are defined! - # This is presumably a bug in SWIG. - #msg_q = di.get_member(u'gr_msg_queue', DoxyClass) - #insert_tail = msg_q.get_member(u'insert_tail', DoxyFunction) - #delete_head = msg_q.get_member(u'delete_head', DoxyFunction) - output = [] - #output.append(make_func_entry(insert_tail, name='gr_py_msg_queue__insert_tail')) - #output.append(make_func_entry(delete_head, name='gr_py_msg_queue__delete_head')) - custom_output = "\n\n".join(output) - - # Generate the docstrings interface file. - make_swig_interface_file(di, swigdocfilename, custom_output=custom_output) + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 53cb61e..dcae02a 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,21 +1,10 @@ # Copyright 2011 Free Software Foundation, Inc. # -# This file is part of gr-osmosdr +# This file was generated by gr_modtool, a tool from the GNU Radio framework +# This file is a part of gr-osmosdr # -# gr-osmosdr 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. +# SPDX-License-Identifier: GPL-3.0-or-later # -# gr-osmosdr 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 gr-osmosdr; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. ######################################################################## # Include python install macros @@ -25,6 +14,8 @@ if(NOT PYTHONINTERP_FOUND) return() endif() +add_subdirectory(bindings) + ######################################################################## # Install python sources ######################################################################## @@ -40,4 +31,3 @@ GR_PYTHON_INSTALL( include(GrTest) set(GR_TEST_TARGET_DEPS gnuradio-osmosdr) -set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) diff --git a/python/__init__.py b/python/__init__.py index 1cb090f..e619f4f 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1,25 +1,24 @@ # # Copyright 2008,2009 Free Software Foundation, Inc. # -# This application 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. -# -# This application 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 this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# SPDX-License-Identifier: GPL-3.0-or-later # # The presence of this file turns this directory into a Python package ''' -This is the GNU Radio OsmoSDR module. +This is the GNU Radio OSMOSDR module. Place your Python package +description here (python/__init__.py). ''' +import os -from .osmosdr_swig import * +# import pybind11 generated symbols into the osmosdr namespace +try: + from .osmosdr_python import * +except ImportError: + dirname, filename = os.path.split(os.path.abspath(__file__)) + __path__.append(os.path.join(dirname, "bindings")) + from .osmosdr_python import * + +# import any pure python here +# diff --git a/python/bindings/CMakeLists.txt b/python/bindings/CMakeLists.txt new file mode 100644 index 0000000..ed50d7e --- /dev/null +++ b/python/bindings/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +GR_PYTHON_CHECK_MODULE_RAW( + "pygccxml" + "import pygccxml" + PYGCCXML_FOUND + ) + +include(GrPybind) + +######################################################################## +# Python Bindings +######################################################################## + +list(APPEND osmosdr_python_files + sink_python.cc + source_python.cc + python_bindings.cc) + +GR_PYBIND_MAKE_OOT(osmosdr + ../.. + gr::osmosdr + "${osmosdr_python_files}") + +install(TARGETS osmosdr_python DESTINATION ${GR_PYTHON_DIR}/osmosdr COMPONENT pythonapi) diff --git a/python/bindings/README.md b/python/bindings/README.md new file mode 100644 index 0000000..e69de29 diff --git a/python/bindings/bind_oot_file.py b/python/bindings/bind_oot_file.py new file mode 100644 index 0000000..55de795 --- /dev/null +++ b/python/bindings/bind_oot_file.py @@ -0,0 +1,53 @@ +import warnings +import argparse +import os +from gnuradio.bindtool import BindingGenerator +import pathlib +import sys + +parser = argparse.ArgumentParser(description='Bind a GR Out of Tree Block') +parser.add_argument('--module', type=str, + help='Name of gr module containing file to bind (e.g. fft digital analog)') + +parser.add_argument('--output_dir', default='/tmp', + help='Output directory of generated bindings') +parser.add_argument('--prefix', help='Prefix of Installed GNU Radio') +parser.add_argument('--src', help='Directory of gnuradio source tree', + default=os.path.dirname(os.path.abspath(__file__))+'/../../..') + +parser.add_argument( + '--filename', help="File to be parsed") + +parser.add_argument( + '--include', help='Additional Include Dirs, separated', default=(), nargs='+') + +parser.add_argument( + '--status', help='Location of output file for general status (used during cmake)', default=None +) +parser.add_argument( + '--flag_automatic', default='0' +) +parser.add_argument( + '--flag_pygccxml', default='0' +) + +args = parser.parse_args() + +prefix = args.prefix +output_dir = args.output_dir +includes = args.include +name = args.module + +namespace = [name] +prefix_include_root = name + + +with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + + bg = BindingGenerator(prefix, namespace, + prefix_include_root, output_dir, addl_includes=','.join(args.include), catch_exceptions=False, write_json_output=False, status_output=args.status, + flag_automatic=True if args.flag_automatic.lower() in [ + '1', 'true'] else False, + flag_pygccxml=True if args.flag_pygccxml.lower() in ['1', 'true'] else False) + bg.gen_file_binding(args.filename) diff --git a/python/bindings/docstrings/README.md b/python/bindings/docstrings/README.md new file mode 100644 index 0000000..295455a --- /dev/null +++ b/python/bindings/docstrings/README.md @@ -0,0 +1 @@ +This directory stores templates for docstrings that are scraped from the include header files for each block \ No newline at end of file diff --git a/python/bindings/docstrings/sink_pydoc_template.h b/python/bindings/docstrings/sink_pydoc_template.h new file mode 100644 index 0000000..dad47cf --- /dev/null +++ b/python/bindings/docstrings/sink_pydoc_template.h @@ -0,0 +1,153 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#include "pydoc_macros.h" +#define D(...) DOC(gr,osmosdr, __VA_ARGS__ ) +/* + This file contains placeholders for docstrings for the Python bindings. + Do not edit! These were automatically extracted during the binding process + and will be overwritten during the build process + */ + + + + static const char *__doc_osmosdr_sink = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_sink_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_sink_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_make = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_num_channels = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_sample_rates = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_sample_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_sample_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_freq_range = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_center_freq = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_center_freq = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_freq_corr = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_freq_corr = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_gain_names = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_gain_range_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_gain_range_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_gain_mode = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_gain_mode = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_gain_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_gain_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_gain_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_gain_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_if_gain = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_bb_gain = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_antennas = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_antenna = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_antenna = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_dc_offset = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_iq_balance = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_bandwidth = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_bandwidth = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_bandwidth_range = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_time_source = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_time_source = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_time_sources = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_clock_source = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_clock_source = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_clock_sources = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_clock_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_clock_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_time_now = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_get_time_last_pps = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_time_now = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_time_next_pps = R"doc()doc"; + + + static const char *__doc_osmosdr_sink_set_time_unknown_pps = R"doc()doc"; + + diff --git a/python/bindings/docstrings/source_pydoc_template.h b/python/bindings/docstrings/source_pydoc_template.h new file mode 100644 index 0000000..f2c3ca4 --- /dev/null +++ b/python/bindings/docstrings/source_pydoc_template.h @@ -0,0 +1,162 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#include "pydoc_macros.h" +#define D(...) DOC(gr,osmosdr, __VA_ARGS__ ) +/* + This file contains placeholders for docstrings for the Python bindings. + Do not edit! These were automatically extracted during the binding process + and will be overwritten during the build process + */ + + + + static const char *__doc_osmosdr_source = R"doc()doc"; + + + static const char *__doc_osmosdr_source_source_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_source_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_make = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_num_channels = R"doc()doc"; + + + static const char *__doc_osmosdr_source_seek = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_sample_rates = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_sample_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_sample_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_freq_range = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_center_freq = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_center_freq = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_freq_corr = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_freq_corr = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_gain_names = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_gain_range_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_gain_range_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_gain_mode = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_gain_mode = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_gain_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_gain_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_gain_0 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_gain_1 = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_if_gain = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_bb_gain = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_antennas = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_antenna = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_antenna = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_dc_offset_mode = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_dc_offset = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_iq_balance_mode = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_iq_balance = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_bandwidth = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_bandwidth = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_bandwidth_range = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_time_source = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_time_source = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_time_sources = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_clock_source = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_clock_source = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_clock_sources = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_clock_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_clock_rate = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_time_now = R"doc()doc"; + + + static const char *__doc_osmosdr_source_get_time_last_pps = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_time_now = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_time_next_pps = R"doc()doc"; + + + static const char *__doc_osmosdr_source_set_time_unknown_pps = R"doc()doc"; + + diff --git a/python/bindings/header_utils.py b/python/bindings/header_utils.py new file mode 100644 index 0000000..165124e --- /dev/null +++ b/python/bindings/header_utils.py @@ -0,0 +1,78 @@ +# Utilities for reading values in header files + +from argparse import ArgumentParser +import re + + +class PybindHeaderParser: + def __init__(self, pathname): + with open(pathname,'r') as f: + self.file_txt = f.read() + + def get_flag_automatic(self): + # p = re.compile(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)', self.file_txt) + if (m and m.group(1) == '1'): + return True + else: + return False + + def get_flag_pygccxml(self): + # p = re.compile(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)', self.file_txt) + if (m and m.group(1) == '1'): + return True + else: + return False + + def get_header_filename(self): + # p = re.compile(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)', self.file_txt) + if (m): + return m.group(1) + else: + return None + + def get_header_file_hash(self): + # p = re.compile(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)', self.file_txt) + if (m): + return m.group(1) + else: + return None + + def get_flags(self): + return f'{self.get_flag_automatic()};{self.get_flag_pygccxml()};{self.get_header_filename()};{self.get_header_file_hash()};' + + + +def argParse(): + """Parses commandline args.""" + desc='Reads the parameters from the comment block in the pybind files' + parser = ArgumentParser(description=desc) + + parser.add_argument("function", help="Operation to perform on comment block of pybind file", choices=["flag_auto","flag_pygccxml","header_filename","header_file_hash","all"]) + parser.add_argument("pathname", help="Pathname of pybind c++ file to read, e.g. blockname_python.cc") + + return parser.parse_args() + +if __name__ == "__main__": + # Parse command line options and set up doxyxml. + args = argParse() + + pbhp = PybindHeaderParser(args.pathname) + + if args.function == "flag_auto": + print(pbhp.get_flag_automatic()) + elif args.function == "flag_pygccxml": + print(pbhp.get_flag_pygccxml()) + elif args.function == "header_filename": + print(pbhp.get_header_filename()) + elif args.function == "header_file_hash": + print(pbhp.get_header_file_hash()) + elif args.function == "all": + print(pbhp.get_flags()) \ No newline at end of file diff --git a/python/bindings/python_bindings.cc b/python/bindings/python_bindings.cc new file mode 100644 index 0000000..fc11ee0 --- /dev/null +++ b/python/bindings/python_bindings.cc @@ -0,0 +1,57 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include + +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include + +namespace py = pybind11; + +// Headers for binding functions +/**************************************/ +/* The following comment block is used for +/* gr_modtool to insert function prototypes +/* Please do not delete +/**************************************/ +// BINDING_FUNCTION_PROTOTYPES( + void bind_sink(py::module& m); + void bind_source(py::module& m); +// ) END BINDING_FUNCTION_PROTOTYPES + + +// We need this hack because import_array() returns NULL +// for newer Python versions. +// This function is also necessary because it ensures access to the C API +// and removes a warning. +void* init_numpy() +{ + import_array(); + return NULL; +} + +PYBIND11_MODULE(osmosdr_python, m) +{ + // Initialize the numpy C API + // (otherwise we will see segmentation faults) + init_numpy(); + + // Allow access to base block methods + py::module::import("gnuradio.gr"); + + /**************************************/ + /* The following comment block is used for + /* gr_modtool to insert binding function calls + /* Please do not delete + /**************************************/ + // BINDING_FUNCTION_CALLS( + bind_sink(m); + bind_source(m); + // ) END BINDING_FUNCTION_CALLS +} diff --git a/python/bindings/sink_python.cc b/python/bindings/sink_python.cc new file mode 100644 index 0000000..1c6711d --- /dev/null +++ b/python/bindings/sink_python.cc @@ -0,0 +1,320 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(1) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(sink.h) */ +/* BINDTOOL_HEADER_FILE_HASH(d4331eb8a19b7a2aa4ed0100039f7a0e) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_sink(py::module& m) +{ + + using sink = ::osmosdr::sink; + + + py::class_>(m, "sink", D(sink)) + + .def(py::init(&sink::make), + py::arg("args") = "", + D(sink,make) + ) + + + + + + .def("get_num_channels",&sink::get_num_channels, + D(sink,get_num_channels) + ) + + + .def("get_sample_rates",&sink::get_sample_rates, + D(sink,get_sample_rates) + ) + + + .def("set_sample_rate",&sink::set_sample_rate, + py::arg("rate"), + D(sink,set_sample_rate) + ) + + + .def("get_sample_rate",&sink::get_sample_rate, + D(sink,get_sample_rate) + ) + + + .def("get_freq_range",&sink::get_freq_range, + py::arg("chan") = 0, + D(sink,get_freq_range) + ) + + + .def("set_center_freq",&sink::set_center_freq, + py::arg("freq"), + py::arg("chan") = 0, + D(sink,set_center_freq) + ) + + + .def("get_center_freq",&sink::get_center_freq, + py::arg("chan") = 0, + D(sink,get_center_freq) + ) + + + .def("set_freq_corr",&sink::set_freq_corr, + py::arg("ppm"), + py::arg("chan") = 0, + D(sink,set_freq_corr) + ) + + + .def("get_freq_corr",&sink::get_freq_corr, + py::arg("chan") = 0, + D(sink,get_freq_corr) + ) + + + .def("get_gain_names",&sink::get_gain_names, + py::arg("chan") = 0, + D(sink,get_gain_names) + ) + + + .def("get_gain_range",(osmosdr::gain_range_t (sink::*)(size_t))&sink::get_gain_range, + py::arg("chan") = 0, + D(sink,get_gain_range,0) + ) + + + .def("get_gain_range",(osmosdr::gain_range_t (sink::*)(std::string const &, size_t))&sink::get_gain_range, + py::arg("name"), + py::arg("chan") = 0, + D(sink,get_gain_range,1) + ) + + + .def("set_gain_mode",&sink::set_gain_mode, + py::arg("automatic"), + py::arg("chan") = 0, + D(sink,set_gain_mode) + ) + + + .def("get_gain_mode",&sink::get_gain_mode, + py::arg("chan") = 0, + D(sink,get_gain_mode) + ) + + + .def("set_gain",(double (sink::*)(double, size_t))&sink::set_gain, + py::arg("gain"), + py::arg("chan") = 0, + D(sink,set_gain,0) + ) + + + .def("set_gain",(double (sink::*)(double, std::string const &, size_t))&sink::set_gain, + py::arg("gain"), + py::arg("name"), + py::arg("chan") = 0, + D(sink,set_gain,1) + ) + + + .def("get_gain",(double (sink::*)(size_t))&sink::get_gain, + py::arg("chan") = 0, + D(sink,get_gain,0) + ) + + + .def("get_gain",(double (sink::*)(std::string const &, size_t))&sink::get_gain, + py::arg("name"), + py::arg("chan") = 0, + D(sink,get_gain,1) + ) + + + .def("set_if_gain",&sink::set_if_gain, + py::arg("gain"), + py::arg("chan") = 0, + D(sink,set_if_gain) + ) + + + .def("set_bb_gain",&sink::set_bb_gain, + py::arg("gain"), + py::arg("chan") = 0, + D(sink,set_bb_gain) + ) + + + .def("get_antennas",&sink::get_antennas, + py::arg("chan") = 0, + D(sink,get_antennas) + ) + + + .def("set_antenna",&sink::set_antenna, + py::arg("antenna"), + py::arg("chan") = 0, + D(sink,set_antenna) + ) + + + .def("get_antenna",&sink::get_antenna, + py::arg("chan") = 0, + D(sink,get_antenna) + ) + + + .def("set_dc_offset",&sink::set_dc_offset, + py::arg("offset"), + py::arg("chan") = 0, + D(sink,set_dc_offset) + ) + + + .def("set_iq_balance",&sink::set_iq_balance, + py::arg("balance"), + py::arg("chan") = 0, + D(sink,set_iq_balance) + ) + + + .def("set_bandwidth",&sink::set_bandwidth, + py::arg("bandwidth"), + py::arg("chan") = 0, + D(sink,set_bandwidth) + ) + + + .def("get_bandwidth",&sink::get_bandwidth, + py::arg("chan") = 0, + D(sink,get_bandwidth) + ) + + + .def("get_bandwidth_range",&sink::get_bandwidth_range, + py::arg("chan") = 0, + D(sink,get_bandwidth_range) + ) + + + .def("set_time_source",&sink::set_time_source, + py::arg("source"), + py::arg("mboard") = 0, + D(sink,set_time_source) + ) + + + .def("get_time_source",&sink::get_time_source, + py::arg("mboard"), + D(sink,get_time_source) + ) + + + .def("get_time_sources",&sink::get_time_sources, + py::arg("mboard"), + D(sink,get_time_sources) + ) + + + .def("set_clock_source",&sink::set_clock_source, + py::arg("source"), + py::arg("mboard") = 0, + D(sink,set_clock_source) + ) + + + .def("get_clock_source",&sink::get_clock_source, + py::arg("mboard"), + D(sink,get_clock_source) + ) + + + .def("get_clock_sources",&sink::get_clock_sources, + py::arg("mboard"), + D(sink,get_clock_sources) + ) + + + .def("get_clock_rate",&sink::get_clock_rate, + py::arg("mboard") = 0, + D(sink,get_clock_rate) + ) + + + .def("set_clock_rate",&sink::set_clock_rate, + py::arg("rate"), + py::arg("mboard") = 0, + D(sink,set_clock_rate) + ) + + + .def("get_time_now",&sink::get_time_now, + py::arg("mboard") = 0, + D(sink,get_time_now) + ) + + + .def("get_time_last_pps",&sink::get_time_last_pps, + py::arg("mboard") = 0, + D(sink,get_time_last_pps) + ) + + + .def("set_time_now",&sink::set_time_now, + py::arg("time_spec"), + py::arg("mboard") = 0, + D(sink,set_time_now) + ) + + + .def("set_time_next_pps",&sink::set_time_next_pps, + py::arg("time_spec"), + D(sink,set_time_next_pps) + ) + + + .def("set_time_unknown_pps",&sink::set_time_unknown_pps, + py::arg("time_spec"), + D(sink,set_time_unknown_pps) + ) + + ; + + + + +} + + + + + + + diff --git a/python/bindings/source_python.cc b/python/bindings/source_python.cc new file mode 100644 index 0000000..48bf10c --- /dev/null +++ b/python/bindings/source_python.cc @@ -0,0 +1,342 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(1) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(source.h) */ +/* BINDTOOL_HEADER_FILE_HASH(574373c3c7682569b0fd7eea577739da) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_source(py::module& m) +{ + + using source = ::osmosdr::source; + + + py::class_>(m, "source", D(source)) + + .def(py::init(&source::make), + py::arg("args") = "", + D(source,make) + ) + + + + + + .def("get_num_channels",&source::get_num_channels, + D(source,get_num_channels) + ) + + + .def("seek",&source::seek, + py::arg("seek_point"), + py::arg("whence"), + py::arg("chan") = 0, + D(source,seek) + ) + + + .def("get_sample_rates",&source::get_sample_rates, + D(source,get_sample_rates) + ) + + + .def("set_sample_rate",&source::set_sample_rate, + py::arg("rate"), + D(source,set_sample_rate) + ) + + + .def("get_sample_rate",&source::get_sample_rate, + D(source,get_sample_rate) + ) + + + .def("get_freq_range",&source::get_freq_range, + py::arg("chan") = 0, + D(source,get_freq_range) + ) + + + .def("set_center_freq",&source::set_center_freq, + py::arg("freq"), + py::arg("chan") = 0, + D(source,set_center_freq) + ) + + + .def("get_center_freq",&source::get_center_freq, + py::arg("chan") = 0, + D(source,get_center_freq) + ) + + + .def("set_freq_corr",&source::set_freq_corr, + py::arg("ppm"), + py::arg("chan") = 0, + D(source,set_freq_corr) + ) + + + .def("get_freq_corr",&source::get_freq_corr, + py::arg("chan") = 0, + D(source,get_freq_corr) + ) + + + .def("get_gain_names",&source::get_gain_names, + py::arg("chan") = 0, + D(source,get_gain_names) + ) + + + .def("get_gain_range",(osmosdr::gain_range_t (source::*)(size_t))&source::get_gain_range, + py::arg("chan") = 0, + D(source,get_gain_range,0) + ) + + + .def("get_gain_range",(osmosdr::gain_range_t (source::*)(std::string const &, size_t))&source::get_gain_range, + py::arg("name"), + py::arg("chan") = 0, + D(source,get_gain_range,1) + ) + + + .def("set_gain_mode",&source::set_gain_mode, + py::arg("automatic"), + py::arg("chan") = 0, + D(source,set_gain_mode) + ) + + + .def("get_gain_mode",&source::get_gain_mode, + py::arg("chan") = 0, + D(source,get_gain_mode) + ) + + + .def("set_gain",(double (source::*)(double, size_t))&source::set_gain, + py::arg("gain"), + py::arg("chan") = 0, + D(source,set_gain,0) + ) + + + .def("set_gain",(double (source::*)(double, std::string const &, size_t))&source::set_gain, + py::arg("gain"), + py::arg("name"), + py::arg("chan") = 0, + D(source,set_gain,1) + ) + + + .def("get_gain",(double (source::*)(size_t))&source::get_gain, + py::arg("chan") = 0, + D(source,get_gain,0) + ) + + + .def("get_gain",(double (source::*)(std::string const &, size_t))&source::get_gain, + py::arg("name"), + py::arg("chan") = 0, + D(source,get_gain,1) + ) + + + .def("set_if_gain",&source::set_if_gain, + py::arg("gain"), + py::arg("chan") = 0, + D(source,set_if_gain) + ) + + + .def("set_bb_gain",&source::set_bb_gain, + py::arg("gain"), + py::arg("chan") = 0, + D(source,set_bb_gain) + ) + + + .def("get_antennas",&source::get_antennas, + py::arg("chan") = 0, + D(source,get_antennas) + ) + + + .def("set_antenna",&source::set_antenna, + py::arg("antenna"), + py::arg("chan") = 0, + D(source,set_antenna) + ) + + + .def("get_antenna",&source::get_antenna, + py::arg("chan") = 0, + D(source,get_antenna) + ) + + + .def("set_dc_offset_mode",&source::set_dc_offset_mode, + py::arg("mode"), + py::arg("chan") = 0, + D(source,set_dc_offset_mode) + ) + + + .def("set_dc_offset",&source::set_dc_offset, + py::arg("offset"), + py::arg("chan") = 0, + D(source,set_dc_offset) + ) + + + .def("set_iq_balance_mode",&source::set_iq_balance_mode, + py::arg("mode"), + py::arg("chan") = 0, + D(source,set_iq_balance_mode) + ) + + + .def("set_iq_balance",&source::set_iq_balance, + py::arg("balance"), + py::arg("chan") = 0, + D(source,set_iq_balance) + ) + + + .def("set_bandwidth",&source::set_bandwidth, + py::arg("bandwidth"), + py::arg("chan") = 0, + D(source,set_bandwidth) + ) + + + .def("get_bandwidth",&source::get_bandwidth, + py::arg("chan") = 0, + D(source,get_bandwidth) + ) + + + .def("get_bandwidth_range",&source::get_bandwidth_range, + py::arg("chan") = 0, + D(source,get_bandwidth_range) + ) + + + .def("set_time_source",&source::set_time_source, + py::arg("source"), + py::arg("mboard") = 0, + D(source,set_time_source) + ) + + + .def("get_time_source",&source::get_time_source, + py::arg("mboard"), + D(source,get_time_source) + ) + + + .def("get_time_sources",&source::get_time_sources, + py::arg("mboard"), + D(source,get_time_sources) + ) + + + .def("set_clock_source",&source::set_clock_source, + py::arg("source"), + py::arg("mboard") = 0, + D(source,set_clock_source) + ) + + + .def("get_clock_source",&source::get_clock_source, + py::arg("mboard"), + D(source,get_clock_source) + ) + + + .def("get_clock_sources",&source::get_clock_sources, + py::arg("mboard"), + D(source,get_clock_sources) + ) + + + .def("get_clock_rate",&source::get_clock_rate, + py::arg("mboard") = 0, + D(source,get_clock_rate) + ) + + + .def("set_clock_rate",&source::set_clock_rate, + py::arg("rate"), + py::arg("mboard") = 0, + D(source,set_clock_rate) + ) + + + .def("get_time_now",&source::get_time_now, + py::arg("mboard") = 0, + D(source,get_time_now) + ) + + + .def("get_time_last_pps",&source::get_time_last_pps, + py::arg("mboard") = 0, + D(source,get_time_last_pps) + ) + + + .def("set_time_now",&source::set_time_now, + py::arg("time_spec"), + py::arg("mboard") = 0, + D(source,set_time_now) + ) + + + .def("set_time_next_pps",&source::set_time_next_pps, + py::arg("time_spec"), + D(source,set_time_next_pps) + ) + + + .def("set_time_unknown_pps",&source::set_time_unknown_pps, + py::arg("time_spec"), + D(source,set_time_unknown_pps) + ) + + ; + + + + +} + + + + + + + diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt deleted file mode 100644 index 159f212..0000000 --- a/swig/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2011 Free Software Foundation, Inc. -# -# This file is part of gr-osmosdr -# -# gr-osmosdr 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. -# -# gr-osmosdr 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 gr-osmosdr; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -######################################################################## -# Include swig generation macros -######################################################################## -find_package(SWIG) -find_package(PythonLibs 3) -if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND) - return() -endif() -include(GrSwig) -include(GrPython) - -######################################################################## -# Setup swig generation -######################################################################## -set(GR_SWIG_INCLUDE_DIRS $) -set(GR_SWIG_TARGET_DEPS gnuradio::runtime_swig) - -set(GR_SWIG_LIBRARIES gnuradio-osmosdr) - -set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/osmosdr_swig_doc.i) -set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/osmosdr) - -GR_SWIG_MAKE(osmosdr_swig osmosdr_swig.i) - -######################################################################## -# Install the build swig module -######################################################################## -GR_SWIG_INSTALL(TARGETS osmosdr_swig DESTINATION ${GR_PYTHON_DIR}/osmosdr) - -######################################################################## -# Install swig .i files for development -######################################################################## -install( - FILES - osmosdr_swig.i - ${CMAKE_CURRENT_BINARY_DIR}/osmosdr_swig_doc.i - DESTINATION ${GR_INCLUDE_DIR}/osmosdr/swig -) diff --git a/swig/osmosdr_swig.i b/swig/osmosdr_swig.i deleted file mode 100644 index da42e6e..0000000 --- a/swig/osmosdr_swig.i +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- c++ -*- */ - -#define OSMOSDR_API - -// suppress Warning 319: No access specifier given for base class 'boost::noncopyable' (ignored). -#pragma SWIG nowarn=319 - -%include "gnuradio.i" // the common stuff - -//load generated python docstrings -%include "osmosdr_swig_doc.i" - -%{ -#include "osmosdr/device.h" -#include "osmosdr/source.h" -#include "osmosdr/sink.h" -%} - -// Workaround for a SWIG 2.0.4 bug with templates. Probably needs to be looked in to. -%{ -#if PY_VERSION_HEX >= 0x03020000 -# define SWIGPY_SLICE_ARG(obj) ((PyObject*) (obj)) -#else -# define SWIGPY_SLICE_ARG(obj) ((PySliceObject*) (obj)) -#endif -%} - -%template(string_vector_t) std::vector; - -//%template(size_vector_t) std::vector; - -%include - -%ignore osmosdr::device_t::operator[]; //ignore warnings about %extend - -%template(string_string_dict_t) std::map; //define before device -%template(devices_t) std::vector; -%include - -//%extend std::map{ -// std::string __getitem__(std::string key) {return (*self)[key];} -// void __setitem__(std::string key, std::string val) {(*self)[key] = val;} -//}; - -%template(range_vector_t) std::vector; //define before range -%include - -%include - -%extend osmosdr::time_spec_t{ - osmosdr::time_spec_t __add__(const osmosdr::time_spec_t &what) - { - osmosdr::time_spec_t temp = *self; - temp += what; - return temp; - } - osmosdr::time_spec_t __sub__(const osmosdr::time_spec_t &what) - { - osmosdr::time_spec_t temp = *self; - temp -= what; - return temp; - } -}; - -%define OSMOSDR_SWIG_BLOCK_MAGIC2(PKG, BASE_NAME) -%template(BASE_NAME ## _sptr) std::shared_ptr; -%pythoncode %{ -BASE_NAME ## _sptr.__repr__ = lambda self: "" % (self.name(), self.unique_id()) -BASE_NAME = BASE_NAME.make; -%} -%enddef - -%include "osmosdr/source.h" -%include "osmosdr/sink.h" - -OSMOSDR_SWIG_BLOCK_MAGIC2(osmosdr,source); -OSMOSDR_SWIG_BLOCK_MAGIC2(osmosdr,sink); - -%{ -static const size_t ALL_MBOARDS = osmosdr::ALL_MBOARDS; -%} -//static const size_t ALL_MBOARDS;