libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/io/caching_file_input.hpp
Go to the documentation of this file.
00001 
00015 /*
00016  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00017  *
00018  *  This file is part of Psychosynth.
00019  *   
00020  *  Psychosynth is free software: you can redistribute it and/or modify
00021  *  it under the terms of the GNU General Public License as published by
00022  *  the Free Software Foundation, either version 3 of the License, or
00023  *  (at your option) any later version.
00024  *
00025  *  Psychosynth is distributed in the hope that it will be useful,
00026  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028  *  GNU General Public License for more details.
00029  *
00030  *  You should have received a copy of the GNU General Public License
00031  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00032  *
00033  */
00034 
00035 #ifndef PSYNTH_IO_CACHING_FILE_READER_H_
00036 #define PSYNTH_IO_CACHING_FILE_READER_H_
00037 
00038 #include <type_traits>
00039 #include <mutex>
00040 #include <thread>
00041 #include <condition_variable>
00042 
00043 #include <boost/pointee.hpp>
00044 
00045 #include <psynth/sound/metafunctions.hpp>
00046 #include <psynth/sound/ring_buffer.hpp>
00047 #include <psynth/io/file_common.hpp>
00048 #include <psynth/io/async_base.hpp>
00049 
00050 namespace psynth
00051 {
00052 namespace io
00053 {
00054 
00055 namespace detail
00056 {
00057 
00058 template <class Range,
00059           class InputPtr> // Models file_input_base
00060 class caching_file_input_impl : public file_input_base<Range>
00061                               , private boost::noncopyable
00062 {
00063 public:
00064     typedef Range range;
00065 
00066     typedef typename boost::pointee<InputPtr>::type  input_type;
00067     typedef typename input_type::range               input_range;
00068 
00069     /*
00070      * High default values for lower number of seeks when reading
00071      * backwards which is in our default usecase.
00072      */
00073     static constexpr std::size_t default_chunk_size  = 1024;
00074     static constexpr std::size_t default_buffer_size = 16384;
00075     static constexpr std::size_t default_threshold   = 4096; 
00076    
00077     caching_file_input_impl (
00078         InputPtr    input       = 0,
00079         std::size_t chunk_size  = default_chunk_size,
00080         std::size_t buffer_size = default_buffer_size,
00081         std::size_t threshold   = default_threshold);
00082 
00083     caching_file_input_impl (
00084         caching_file_input_impl&& other) = default;
00085 
00086     ~caching_file_input_impl ();
00087     
00088 #if 0 // TODO
00089     caching_file_input_impl& operator= (
00090         caching_file_input_impl&& other) = default;
00091 #endif
00092     
00093     void start ();
00094     void stop ();
00095 
00096     std::size_t frame_rate () const
00097     { return _input->frame_rate (); }
00098 
00099     std::size_t length () const
00100     { return _input->length (); }
00101 
00102     const input_type& input () const
00103     { return *_input; }
00104     
00105     bool is_backwards () const
00106     { return _backwards; }
00107     
00108     void set_backwards (bool backwards);
00109 
00111     void set_chunk_size (std::size_t cs)
00112     { _chunk_size = cs; }
00113 
00114     void soft_seek (std::size_t pos);
00115     std::size_t seek (std::ptrdiff_t pos, seek_dir dir);
00116     
00117     std::size_t take (const range& buf)
00118     { return this->template take<range> (buf); }
00119 
00120     template <class Range2>
00121     std::size_t take (const Range2& buf);
00122 
00123 protected:
00124     InputPtr      _input;
00125     
00126 public:
00127     typedef typename sound::buffer_from_range<input_range>::type
00128     input_buffer_type;
00129 
00130     typedef typename sound::buffer_from_range<range>::type
00131     buffer_type;
00132     
00133     typedef sound::ring_buffer<buffer_type> ring_buffer_type;
00134 
00135     void set_input (InputPtr ptr);
00136 
00137     void do_seek (std::ptrdiff_t offst, seek_dir dir);
00138     
00139     std::size_t   _chunk_size; // TODO: This substitutes
00140                                // get_info().block_size, but there
00141                                // might be problems.
00142     std::size_t   _buffer_size;
00143     std::size_t   _threshold;
00144     
00145     input_buffer_type                   _tmp_buffer;
00146     ring_buffer_type                    _buffer;
00147     typename ring_buffer_type::range&   _range;
00148     typename ring_buffer_type::position _read_ptr;
00149     
00150     bool           _backwards;
00151     std::ptrdiff_t _read_pos;
00152     std::ptrdiff_t _new_read_pos;
00153 
00154     std::atomic<bool> _finished;
00155 
00156     std::thread             _thread;
00157     std::mutex              _input_mutex;
00158     std::mutex              _buffer_mutex;
00159     std::condition_variable _cond;
00160     
00161     void run ();
00162 };
00163 
00164 } /* namespace detail */
00165 
00166 template <class Range, class InputPtr>
00167 class caching_file_input_adapter :
00168         public detail::caching_file_input_impl<Range, InputPtr>
00169 {
00170 public:
00171     typedef detail::caching_file_input_impl<Range, InputPtr> base;
00172     
00173     caching_file_input_adapter (
00174         InputPtr    input       = 0,
00175         std::size_t chunk_size  = base::default_chunk_size,
00176         std::size_t buffer_size = base::default_buffer_size,
00177         std::size_t threshold   = base::default_threshold)
00178         : base (input, chunk_size, buffer_size, threshold)
00179     {}
00180 
00181     caching_file_input_adapter (caching_file_input_adapter&& other)
00182         : base (std::move (other))
00183     {}
00184 
00185     void set_input (InputPtr input)
00186     { base::set_input (input); }
00187 };
00188 
00189 } /* namespace io */
00190 } /* namespace psynth */
00191 
00192 #include <psynth/io/caching_file_input.tpp>
00193 
00194 #endif /* PSYNTH_IO_CACHING_FILE_INPUT_H_ */
00195