|
libpsynth 0.2.1
|
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
1.7.4