libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/io/buffered_output.hpp
Go to the documentation of this file.
00001 
00019 /*
00020  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00021  *
00022  *  This file is part of Psychosynth.
00023  *   
00024  *  Psychosynth is free software: you can redistribute it and/or modify
00025  *  it under the terms of the GNU General Public License as published by
00026  *  the Free Software Foundation, either version 3 of the License, or
00027  *  (at your option) any later version.
00028  *
00029  *  Psychosynth is distributed in the hope that it will be useful,
00030  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00031  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00032  *  GNU General Public License for more details.
00033  *
00034  *  You should have received a copy of the GNU General Public License
00035  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00036  *
00037  */
00038 
00039 #ifndef PSYNTH_IO_BUFFERED_OUTPUT_H_
00040 #define PSYNTH_IO_BUFFERED_OUTPUT_H_
00041 
00042 
00043 #include <psynth/base/type_traits.hpp>
00044 #include <psynth/sound/metafunctions.hpp>
00045 #include <psynth/io/output.hpp>
00046 
00047 namespace psynth
00048 {
00049 namespace io
00050 {
00051 
00052 namespace detail
00053 {
00054 
00055 template <class Base, // either output or async_output
00056           class OutputPtr> 
00057 class buffered_output_impl : public Base
00058 {
00059 public:
00060     typedef typename Base::range range;
00061     typedef typename Base::const_range const_range;
00062     
00063     typedef typename base::pointee<OutputPtr>::type output_type;
00064     typedef typename output_type::range output_range;
00065     typedef typename output_type::const_range output_const_range;
00066 
00067     typedef typename sound::buffer_from_range<output_range>::type
00068     buffer_type;
00069 
00070     buffered_output_impl (OutputPtr output_ptr = 0)
00071         : _buffer (default_output_buffer_size)
00072         , _output_ptr (output_ptr)
00073     {}
00074     
00075     std::size_t put (const const_range& data);
00076     
00077     template <class Range2>
00078     std::size_t put (const Range2& data);
00079 
00080     output_type& output ()
00081     { return *_output_ptr; }
00082 
00083     const output_type& output () const
00084     { return *_output_ptr; }
00085 
00086     const buffer_type& buffer () const
00087     { return _buffer; }
00088     
00089     void set_buffer_size (std::size_t new_size)
00090     { _buffer.recreate (new_size); }
00091 
00092 protected:
00093     void set_output (OutputPtr ptr)
00094     {
00095         _output_ptr = ptr;
00096     }
00097 
00098     buffer_type _buffer;
00099     OutputPtr   _output_ptr;
00100 };
00101 
00102 template <class Base, class OutputPtr> 
00103 class buffered_async_output_impl :
00104         public buffered_output_impl<Base, OutputPtr>
00105 {
00106 public:
00107     typedef buffered_output_impl<Base, OutputPtr> base;
00108     typedef typename base::callback_type callback_type;
00109     
00110     buffered_async_output_impl (OutputPtr output_ptr = 0)
00111         : base (output_ptr)
00112     {}
00113 
00114     void fit_buffer ();
00115 
00116     std::size_t buffer_size () const
00117     { return this->_output_ptr->buffer_size (); }
00118 
00119     void start ()
00120     { this->_output_ptr->start (); }
00121 
00122     void stop ()
00123     { this->_output_ptr->stop (); }
00124 
00125     async_state state () const
00126     { return this->_output_ptr->state (); }
00127 
00128     void set_callback (callback_type cb)
00129     { this->_output_ptr->set_callback (cb); }
00130 };
00131 
00132 } /* namespace detail */
00133 
00134 
00135 template <class Range, class OutputPtr>
00136 class buffered_output_adapter :
00137     public detail::buffered_output_impl<output<Range>, OutputPtr>
00138 {
00139 public:
00140     typedef detail::buffered_output_impl<output<Range>, OutputPtr> base;
00141     
00142     buffered_output_adapter (OutputPtr out = 0)
00143         : base (out)
00144     { }
00145     
00146     void set_output (OutputPtr out = 0)
00147     { base::set_output (out); }
00148 };
00149 
00150 
00151 template <class Range, class Output>
00152 class buffered_output :
00153     public detail::buffered_output_impl<output<Range>, Output*>
00154 {   
00155 public:
00156     typedef detail::buffered_output_impl<output<Range>, Output*> base;
00157  
00158     template <typename... Args>
00159     buffered_output (Args... args)
00160         : base (&_output)
00161         , _output (args...)
00162     {}
00163 
00164 private:
00165     Output _output;
00166 };
00167 
00168 
00169 template <class Range, class OutputPtr>
00170 class buffered_async_output_adapter :
00171     public detail::buffered_async_output_impl<async_output<Range>, OutputPtr>
00172 {
00173 public:
00174     typedef detail::buffered_async_output_impl<async_output<Range>,
00175                                                OutputPtr> base;
00176     
00177     buffered_async_output_adapter (OutputPtr out = 0)
00178         : base (out)
00179     { this->fit_buffer (); }
00180     
00181     void set_output (OutputPtr out = 0)
00182     {
00183         this->set_output (out);
00184         this->fit_buffer ();
00185     }
00186 };
00187 
00188 
00189 template <class Range, class Output>
00190 class buffered_async_output :
00191     public detail::buffered_async_output_impl<async_output<Range>, Output*>
00192 {
00193 public:   
00194     typedef detail::buffered_async_output_impl<async_output<Range>,
00195                                                Output*> base;
00196 
00200     template <typename... Args>
00201     buffered_async_output (Args... args)
00202         : base (&_output)
00203         , _output (args...)
00204     {
00205         this->fit_buffer ();
00206     }
00207 
00208 private:
00209     Output _output;
00210 };
00211 
00212 namespace detail
00213 {
00214 
00215 template <class OutputPtr>
00216 struct is_async_ptr : public std::is_base_of<
00217     async_base,
00218     typename boost::pointee<OutputPtr>::type> {};
00219 
00220 } /* namespace detail */
00221 
00222 template <class Range, class OutputPtr>
00223 typename std::enable_if<
00224     !detail::is_async_ptr<OutputPtr>::value,
00225     buffered_output_adapter<Range, OutputPtr>
00226     >::type
00227 make_buffered_output (OutputPtr out)
00228 {
00229     return buffered_output_adapter<Range, OutputPtr> (out);
00230 }
00231 
00232 template <class Range, class OutputPtr>
00233 typename std::enable_if<
00234     detail::is_async_ptr<OutputPtr>::value,
00235     buffered_async_output_adapter<Range, OutputPtr>
00236     >::type
00237 make_buffered_output (OutputPtr out)
00238 {
00239     return buffered_async_output_adapter<Range, OutputPtr> (out);
00240 }
00241 
00242 } /* namespace io */
00243 } /* namespace psynth */
00244 
00245 #include <psynth/io/buffered_output.tpp>
00246 
00247 #endif /* PSYNTH_IO_BUFFERED_OUTPUT_H_ */
00248