From e3732c0609fd25e3da3e9bcf25d6aaece88373fb Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 26 Oct 2013 21:06:04 +0200 Subject: [PATCH] gr-fosphor: Add WX widget version of the fosphor sink Signed-off-by: Sylvain Munaut --- grc/CMakeLists.txt | 4 +- grc/fosphor_wx_sink_c.xml | 43 +++++++++ include/gnuradio/fosphor/CMakeLists.txt | 1 + include/gnuradio/fosphor/wx_core_sink_c.h | 59 ++++++++++++ lib/CMakeLists.txt | 3 + lib/wx_core_sink_c_impl.cc | 110 ++++++++++++++++++++++ lib/wx_core_sink_c_impl.h | 64 +++++++++++++ python/CMakeLists.txt | 1 + python/__init__.py | 1 + python/wx_sink_c.py | 93 ++++++++++++++++++ swig/fosphor_swig.i | 4 + 11 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 grc/fosphor_wx_sink_c.xml create mode 100644 include/gnuradio/fosphor/wx_core_sink_c.h create mode 100644 lib/wx_core_sink_c_impl.cc create mode 100644 lib/wx_core_sink_c_impl.h create mode 100644 python/wx_sink_c.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 1898caa..3445fa0 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -17,5 +17,7 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. install(FILES - fosphor_glfw_sink_c.xml DESTINATION share/gnuradio/grc/blocks + fosphor_glfw_sink_c.xml + fosphor_wx_sink_c.xml + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/fosphor_wx_sink_c.xml b/grc/fosphor_wx_sink_c.xml new file mode 100644 index 0000000..daa93fe --- /dev/null +++ b/grc/fosphor_wx_sink_c.xml @@ -0,0 +1,43 @@ + + + WX fosphor sink + fosphor_wx_sink_c + Instrumentation/WX + from gnuradio import fosphor + #set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self' +fosphor.wx_sink_c( + $(parent).GetWin() +#if $win_size() + size=$win_size, +#end if +) +#if not $grid_pos() +$(parent).Add(self.$(id).win) +#else +$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos())))) +#end if + + Window Size + win_size + + int_vector + #if $win_size() then 'none' else 'part'# + + + Grid Position + grid_pos + + grid_pos + + + Notebook + notebook + + notebook + + not $win_size or len($win_size) == 2 + + in + complex + + diff --git a/include/gnuradio/fosphor/CMakeLists.txt b/include/gnuradio/fosphor/CMakeLists.txt index 91a1fea..eb38aa8 100644 --- a/include/gnuradio/fosphor/CMakeLists.txt +++ b/include/gnuradio/fosphor/CMakeLists.txt @@ -24,5 +24,6 @@ install(FILES api.h base_sink_c.h glfw_sink_c.h + wx_core_sink_c.h DESTINATION include/gnuradio/fosphor ) diff --git a/include/gnuradio/fosphor/wx_core_sink_c.h b/include/gnuradio/fosphor/wx_core_sink_c.h new file mode 100644 index 0000000..89c8606 --- /dev/null +++ b/include/gnuradio/fosphor/wx_core_sink_c.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Sylvain Munaut + * + * This 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 software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_GR_FOSPHOR_WX_CORE_SINK_C_H +#define INCLUDED_GR_FOSPHOR_WX_CORE_SINK_C_H + +#include +#include + +#include + +namespace gr { + namespace fosphor { + + /*! + * \brief WX version of fosphor sink (core) + * \ingroup fosphor + */ + class GR_FOSPHOR_API wx_core_sink_c : virtual public base_sink_c + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of fosphor::wx_core_sink_c. + * + * To avoid accidental use of raw pointers, fosphor::wx_core_sink_c's + * constructor is in a private implementation + * class. fosphor::wx_core_sink_c::make is the public interface for + * creating new instances. + */ + static sptr make(PyObject *cb_init, PyObject *cb_fini, PyObject *cb_swap); + + virtual void pycb_reshape(int width, int height) = 0; + }; + + } // namespace fosphor +} // namespace gr + +#endif /* INCLUDED_GR_FOSPHOR_WX_CORE_SINK_C_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 053bd8d..f095de2 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -23,6 +23,7 @@ include(GrPlatform) #define LIB_SUFFIX include(GrMiscUtils) +find_package(PythonLibs 2) find_package(PythonInterp 2) add_custom_command( @@ -39,6 +40,7 @@ include_directories( ${OPENCL_INCLUDE_DIRS} ${FREETYPE2_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIRS} ) link_directories( ${OPENGL_LIBRARY_DIRS} @@ -60,6 +62,7 @@ list(APPEND fosphor_sources fifo.cc base_sink_c_impl.cc glfw_sink_c_impl.cc + wx_core_sink_c_impl.cc ) add_library(gnuradio-fosphor SHARED ${fosphor_sources}) diff --git a/lib/wx_core_sink_c_impl.cc b/lib/wx_core_sink_c_impl.cc new file mode 100644 index 0000000..c4ec33f --- /dev/null +++ b/lib/wx_core_sink_c_impl.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Sylvain Munaut + * + * This 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 software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "wx_core_sink_c_impl.h" + + +namespace gr { + namespace fosphor { + +wx_core_sink_c::sptr +wx_core_sink_c::make(PyObject *cb_init, PyObject *cb_fini, PyObject *cb_swap) +{ + return gnuradio::get_initial_sptr(new wx_core_sink_c_impl(cb_init, cb_fini, cb_swap)); +} + +wx_core_sink_c_impl::wx_core_sink_c_impl(PyObject *cb_init, PyObject *cb_fini, PyObject *cb_swap) + : base_sink_c("wx_core_sink_c"), + d_cb_init(cb_init), d_cb_fini(cb_fini), d_cb_swap(cb_swap) +{ + /* Make sure we keep reference to callbacks */ + Py_INCREF(this->d_cb_init); + Py_INCREF(this->d_cb_fini); + Py_INCREF(this->d_cb_swap); +} + +wx_core_sink_c_impl::~wx_core_sink_c_impl() +{ + /* Release callbacks */ + Py_DECREF(this->d_cb_init); + Py_DECREF(this->d_cb_fini); + Py_DECREF(this->d_cb_swap); +} + + +void +wx_core_sink_c_impl::pycall(PyObject *cb) +{ + PyObject *arglist; + PyObject *result; + + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + + arglist = Py_BuildValue("()"); + result = PyEval_CallObject(cb, arglist); + Py_DECREF(arglist); + + if (result != NULL) + Py_DECREF(result); + + PyGILState_Release(gstate); +} + + +void +wx_core_sink_c_impl::glctx_init() +{ + this->pycall(this->d_cb_init); +} + +void +wx_core_sink_c_impl::glctx_swap() +{ + this->pycall(this->d_cb_swap); +} + +void +wx_core_sink_c_impl::glctx_poll() +{ + /* Nothing to do */ +} + +void +wx_core_sink_c_impl::glctx_fini() +{ + this->pycall(this->d_cb_fini); +} + + +void +wx_core_sink_c_impl::pycb_reshape(int width, int height) +{ + this->cb_reshape(width, height); +} + + } /* namespace fosphor */ +} /* namespace gr */ diff --git a/lib/wx_core_sink_c_impl.h b/lib/wx_core_sink_c_impl.h new file mode 100644 index 0000000..1dd0c17 --- /dev/null +++ b/lib/wx_core_sink_c_impl.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Sylvain Munaut + * + * This 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 software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_GR_FOSPHOR_WX_CORE_SINK_C_IMPL_H +#define INCLUDED_GR_FOSPHOR_WX_CORE_SINK_C_IMPL_H + +#include + +#include "base_sink_c_impl.h" + +namespace gr { + namespace fosphor { + + /*! + * \brief WX version of fosphor sink (core implementation) + * \ingroup fosphor + */ + class wx_core_sink_c_impl : public wx_core_sink_c, public base_sink_c_impl + { + private: + /* Delegation to python */ + void pycall(PyObject *cb); + + PyObject *d_cb_init; + PyObject *d_cb_fini; + PyObject *d_cb_swap; + + protected: + /* Delegated implementation of GL context management */ + void glctx_init(); + void glctx_swap(); + void glctx_poll(); + void glctx_fini(); + + public: + wx_core_sink_c_impl(PyObject *cb_init, PyObject *cb_fini, PyObject *cb_swap); + ~wx_core_sink_c_impl(); + + void pycb_reshape(int width, int height); + }; + + } // namespace fosphor +} // namespace gr + +#endif /* INCLUDED_GR_FOSPHOR_WX_CORE_SINK_C_IMPL_H */ + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 27b3c7e..c09a23d 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -31,6 +31,7 @@ endif() GR_PYTHON_INSTALL( FILES __init__.py + wx_sink_c.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/fosphor ) diff --git a/python/__init__.py b/python/__init__.py index 63d3da9..fbe4be3 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -45,6 +45,7 @@ if _RTLD_GLOBAL != 0: from fosphor_swig import * # import any pure python here +from wx_sink_c import wx_sink_c # # ---------------------------------------------------------------- diff --git a/python/wx_sink_c.py b/python/wx_sink_c.py new file mode 100644 index 0000000..da10879 --- /dev/null +++ b/python/wx_sink_c.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2013 Sylvain Munaut +# +# This 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 software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import numpy + +import wx +import wx.glcanvas +from OpenGL import GL + +from gnuradio import gr + +from fosphor_swig import base_sink_c, wx_core_sink_c + +import threading + +class wx_sink_c(gr.hier_block2): + + def __init__(self, parent, size=(600,600)): + gr.hier_block2.__init__( + self, + "wx_sink_c", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(0, 0, 0), + ) + + # Create the GL Canvas (without context for now) + attribList = (wx.glcanvas.WX_GL_DOUBLEBUFFER, wx.glcanvas.WX_GL_RGBA) + self.win = wx.glcanvas.GLCanvas(parent, wx.ID_ANY, + attribList=attribList, + size=size, + style=wx.WANTS_CHARS + ) + + self.win.Bind(wx.EVT_SIZE, self._evt_size) + self.win.Bind(wx.EVT_KEY_DOWN, self._evt_key_down) + self.win.SetFocus() + + self._gl_ctx = None + + # Create the underlying WX sink core + self.sink = wx_core_sink_c(self._glctx_init, self._glctx_fini, self._glctx_swap) + self.connect(self, self.sink) + + def _evt_size(self, evt): + self.sink.pycb_reshape(*evt.GetSize()) + + def _evt_key_down(self, evt): + k = evt.GetKeyCode() + if k == wx.WXK_UP: + self.sink.execute_ui_action(base_sink_c.REF_DOWN) + elif k == wx.WXK_DOWN: + self.sink.execute_ui_action(base_sink_c.REF_UP) + elif k == wx.WXK_LEFT: + self.sink.execute_ui_action(base_sink_c.DB_PER_DIV_DOWN) + elif k == wx.WXK_RIGHT: + self.sink.execute_ui_action(base_sink_c.DB_PER_DIV_UP) + else: + evt.Skip() + + def _glctx_init(self): + if self._gl_ctx is None: + self._gl_ctx = wx.glcanvas.GLContext(self.win) + self.win.SetCurrent(self._gl_ctx) + + def _glctx_fini(self): + self._gl_ctx = None + + def _glctx_swap(self): + self.win.SwapBuffers() + + def __getattr__(self, attr): + try: + return gr.hier_block2.__getattr__(self, attr) + except: + return getattr(self.sink, attr) diff --git a/swig/fosphor_swig.i b/swig/fosphor_swig.i index 2ef3c20..1812de5 100644 --- a/swig/fosphor_swig.i +++ b/swig/fosphor_swig.i @@ -9,6 +9,7 @@ %{ #include "gnuradio/fosphor/glfw_sink_c.h" +#include "gnuradio/fosphor/wx_core_sink_c.h" %} @@ -17,3 +18,6 @@ %nodefaultctor gr::fosphor::glfw_sink_c; // bug workaround %include "gnuradio/fosphor/glfw_sink_c.h" GR_SWIG_BLOCK_MAGIC2(fosphor, glfw_sink_c); + +%include "gnuradio/fosphor/wx_core_sink_c.h" +GR_SWIG_BLOCK_MAGIC2(fosphor, wx_core_sink_c);