| 1 |
|
|---|
| 2 | #include <stdafx.h>
|
|---|
| 3 | #include "looping.h"
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 | bool open_path_helper(input_decoder::ptr & p_input, file::ptr p_file, const char * path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
|
|---|
| 8 | p_abort.check();
|
|---|
| 9 | p_input.release();
|
|---|
| 10 |
|
|---|
| 11 | TRACK_CODE("input_entry::g_open_for_decoding",
|
|---|
| 12 | input_entry::g_open_for_decoding(p_input,p_file,path,p_abort,p_from_redirect)
|
|---|
| 13 | );
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 | if (!p_skip_hints) {
|
|---|
| 17 | try {
|
|---|
| 18 | static_api_ptr_t<metadb_io>()->hint_reader(p_input.get_ptr(),path,p_abort);
|
|---|
| 19 | } catch(exception_io_data) {
|
|---|
| 20 | //Don't fail to decode when this barfs, might be barfing when reading info from another subsong than the one we're trying to decode etc.
|
|---|
| 21 | p_input.release();
|
|---|
| 22 | if (p_file.is_valid()) p_file->reopen(p_abort);
|
|---|
| 23 | TRACK_CODE("input_entry::g_open_for_decoding",
|
|---|
| 24 | input_entry::g_open_for_decoding(p_input,p_file,path,p_abort,p_from_redirect)
|
|---|
| 25 | );
|
|---|
| 26 | }
|
|---|
| 27 | }
|
|---|
| 28 |
|
|---|
| 29 | return true;
|
|---|
| 30 | }
|
|---|
| 31 |
|
|---|
| 32 | bool parse_entity(const char * & ptr,pfc::string8 & name,pfc::string8 & value) {
|
|---|
| 33 | char delimiter = '\0';
|
|---|
| 34 | char tmp;
|
|---|
| 35 | t_size n = 0;
|
|---|
| 36 | while(isspace(*ptr)) ptr++;
|
|---|
| 37 | while(tmp = ptr[n], tmp && !isspace(tmp) && tmp != '=') n++;
|
|---|
| 38 | if (!ptr[n]) return false;
|
|---|
| 39 | name.set_string(ptr, n);
|
|---|
| 40 | ptr += n;
|
|---|
| 41 | while(isspace(*ptr)) ptr++;
|
|---|
| 42 | if (*ptr != '=') return false;
|
|---|
| 43 | ptr++;
|
|---|
| 44 | // check delimiter
|
|---|
| 45 | if (*ptr == '\'' || *ptr == '"') {
|
|---|
| 46 | delimiter = *ptr;
|
|---|
| 47 | ptr++;
|
|---|
| 48 | }
|
|---|
| 49 | if (!*ptr) false;
|
|---|
| 50 |
|
|---|
| 51 | n = 0;
|
|---|
| 52 | if (delimiter == '\0') {
|
|---|
| 53 | while(tmp = ptr[n], tmp && !isspace(tmp) && tmp != ';') n++;
|
|---|
| 54 | } else {
|
|---|
| 55 | while(tmp = ptr[n], tmp && tmp != delimiter) n++;
|
|---|
| 56 | }
|
|---|
| 57 | if (!ptr[n]) return false;
|
|---|
| 58 | value.set_string(ptr, n);
|
|---|
| 59 | ptr += n;
|
|---|
| 60 | if (*ptr == delimiter) ptr++;
|
|---|
| 61 | while(*ptr == ';' || isspace(*ptr)) ptr++;
|
|---|
| 62 | return true;
|
|---|
| 63 | }
|
|---|
| 64 |
|
|---|
| 65 | t_filestats merge_filestats(const t_filestats & p_src1, const t_filestats & p_src2, int p_merge_type) {
|
|---|
| 66 | t_filestats dest;
|
|---|
| 67 | dest.m_timestamp = pfc::max_t(p_src1.m_timestamp, p_src2.m_timestamp);
|
|---|
| 68 | if (p_merge_type == merge_filestats_sum) {
|
|---|
| 69 | dest.m_size = p_src1.m_size + p_src2.m_size;
|
|---|
| 70 | } else if (p_merge_type == merge_filestats_max) {
|
|---|
| 71 | dest.m_size = pfc::max_t(p_src1.m_size, p_src2.m_size);
|
|---|
| 72 | } else {
|
|---|
| 73 | throw pfc::exception_not_implemented();
|
|---|
| 74 | }
|
|---|
| 75 | return dest;
|
|---|
| 76 | }
|
|---|
| 77 |
|
|---|
| 78 | // some looping type class
|
|---|
| 79 | class input_loop_type_loopstartlength : public input_loop_type_impl_singlefile_base
|
|---|
| 80 | {
|
|---|
| 81 | private:
|
|---|
| 82 | input_decoder::ptr m_input;
|
|---|
| 83 | input_loop_event_point_list m_points;
|
|---|
| 84 | public:
|
|---|
| 85 | static const char * g_get_name() {return "LoopStart/LoopLength";}
|
|---|
| 86 | static const char * g_get_short_name() {return "loopstartlength";}
|
|---|
| 87 | static bool g_is_our_type(const char * type) {return !pfc::stringCompareCaseInsensitive(type, "loopstartlength");}
|
|---|
| 88 | static bool g_is_explicit() {return false;}
|
|---|
| 89 | virtual bool parse(const char * ptr) {
|
|---|
| 90 | return true;
|
|---|
| 91 | }
|
|---|
| 92 | virtual bool open_path_internal(file::ptr p_filehint,const char * path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
|
|---|
| 93 | try {
|
|---|
| 94 | open_path_helper(m_input, p_filehint, path, p_abort, p_from_redirect,p_skip_hints);
|
|---|
| 95 | } catch (exception_io_not_found) {
|
|---|
| 96 | return false;
|
|---|
| 97 | }
|
|---|
| 98 | switch_input(m_input);
|
|---|
| 99 | file_info_impl p_info;
|
|---|
| 100 | get_input()->get_info(0, p_info, p_abort);
|
|---|
| 101 | m_points.remove_all();
|
|---|
| 102 | if (p_info.meta_get_count_by_name("LOOPSTART") != 1 ||
|
|---|
| 103 | p_info.meta_get_count_by_name("LOOPLENGTH") != 1)
|
|---|
| 104 | return false;
|
|---|
| 105 | input_loop_event_point_simple * point = new service_impl_t<input_loop_event_point_simple>();
|
|---|
| 106 | t_uint64 start = pfc::atoui64_ex(p_info.meta_get("LOOPSTART", 0), infinite_size);
|
|---|
| 107 | t_uint64 length = pfc::atoui64_ex(p_info.meta_get("LOOPLENGTH", 0), infinite_size);
|
|---|
| 108 | point->from = start + length;
|
|---|
| 109 | point->to = start;
|
|---|
| 110 | m_points.add_item(point);
|
|---|
| 111 | switch_points(m_points);
|
|---|
| 112 | return true;
|
|---|
| 113 | }
|
|---|
| 114 | virtual void get_info(t_uint32 subsong, file_info & p_info,abort_callback & p_abort) {
|
|---|
| 115 | get_input()->get_info(subsong, p_info, p_abort);
|
|---|
| 116 | get_info_for_points(p_info, m_points, get_info_prefix(), get_sample_rate());
|
|---|
| 117 | }
|
|---|
| 118 | };
|
|---|
| 119 |
|
|---|
| 120 | static input_loop_type_factory_t<input_loop_type_loopstartlength> g_input_loop_type_loopstartlength;
|
|---|
| 121 |
|
|---|
| 122 | class input_loop_event_point_twofiles_eof : public input_loop_event_point_baseimpl {
|
|---|
| 123 | public:
|
|---|
| 124 | virtual t_uint64 get_position() const {return infinite64;}
|
|---|
| 125 | virtual t_uint64 get_prepare_position() const {return infinite64;}
|
|---|
| 126 | virtual void get_info(file_info & p_info, const char * p_prefix, t_uint32 sample_rate) {}
|
|---|
| 127 | virtual bool process(input_loop_type_base::ptr p_input, t_uint64 p_start, audio_chunk & p_chunk, mem_block_container * p_raw, abort_callback & p_abort) {
|
|---|
| 128 | // no truncate (because EOF)
|
|---|
| 129 | return process(p_input, p_abort);
|
|---|
| 130 | }
|
|---|
| 131 | virtual bool process(input_loop_type_base::ptr p_input, abort_callback & p_abort);
|
|---|
| 132 | };
|
|---|
| 133 |
|
|---|
| 134 |
|
|---|
| 135 | class input_loop_type_twofiles : public input_loop_type_impl_base
|
|---|
| 136 | {
|
|---|
| 137 | private:
|
|---|
| 138 | struct somefile {
|
|---|
| 139 | input_decoder::ptr input;
|
|---|
| 140 | pfc::string8 suffix;
|
|---|
| 141 | pfc::string8 path;
|
|---|
| 142 | t_uint64 samples;
|
|---|
| 143 | bool samples_known;
|
|---|
| 144 | };
|
|---|
| 145 | input_loop_event_point_list m_points;
|
|---|
| 146 | somefile * m_current;
|
|---|
| 147 | somefile m_head, m_body;
|
|---|
| 148 | pfc::string8 m_current_fileext;
|
|---|
| 149 | bool m_current_changed;
|
|---|
| 150 |
|
|---|
| 151 | inline void switch_to(somefile & newfile) {
|
|---|
| 152 | if (m_current != &newfile) {
|
|---|
| 153 | m_current_changed = true;
|
|---|
| 154 | }
|
|---|
| 155 | m_current = &newfile;
|
|---|
| 156 | switch_input(newfile.input);
|
|---|
| 157 | m_current_fileext = pfc::string_filename_ext(newfile.path);
|
|---|
| 158 | }
|
|---|
| 159 |
|
|---|
| 160 | protected:
|
|---|
| 161 | void virtual open_decoding_internal(t_uint32 subsong, t_uint32 flags, abort_callback & p_abort) {
|
|---|
| 162 | m_head.input->initialize(subsong, flags, p_abort);
|
|---|
| 163 | m_body.input->initialize(subsong, flags, p_abort);
|
|---|
| 164 | }
|
|---|
| 165 | virtual bool set_dynamic_info_track(file_info & p_out) {
|
|---|
| 166 | bool ret = input_loop_type_impl_base::set_dynamic_info_track(p_out);
|
|---|
| 167 | if (m_current_changed) {
|
|---|
| 168 | p_out.info_set("loop_current_file", m_current_fileext);
|
|---|
| 169 | return true;
|
|---|
| 170 | } else {
|
|---|
| 171 | return ret;
|
|---|
| 172 | }
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | virtual bool reset_dynamic_info_track(file_info & p_out) {
|
|---|
| 176 | return input_loop_type_impl_base::reset_dynamic_info_track(p_out) |
|
|---|
| 177 | p_out.info_remove("loop_current_file");
|
|---|
| 178 | }
|
|---|
| 179 | public:
|
|---|
| 180 | static const char * g_get_name() {return "Two Files (head and body)";}
|
|---|
| 181 | static const char * g_get_short_name() {return "twofiles";}
|
|---|
| 182 | static bool g_is_our_type(const char * type) {return !pfc::stringCompareCaseInsensitive(type, "twofiles");}
|
|---|
| 183 | static bool g_is_explicit() {return true;}
|
|---|
| 184 | virtual bool parse(const char * ptr) {
|
|---|
| 185 | pfc::string8 name, value;
|
|---|
| 186 | while (parse_entity(ptr, name, value)) {
|
|---|
| 187 | if (!pfc::stringCompareCaseInsensitive(name, "head-suffix")) {
|
|---|
| 188 | m_head.suffix = value;
|
|---|
| 189 | } else if (!pfc::stringCompareCaseInsensitive(name, "body-suffix")) {
|
|---|
| 190 | m_body.suffix = value;
|
|---|
| 191 | } else {
|
|---|
| 192 | // ignore unknown entities
|
|---|
| 193 | //return false;
|
|---|
| 194 | }
|
|---|
| 195 | }
|
|---|
| 196 | if (m_head.suffix == m_body.suffix) return false;
|
|---|
| 197 | return true;
|
|---|
| 198 | }
|
|---|
| 199 | virtual bool open_path_internal(file::ptr p_filehint,const char * p_path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
|
|---|
| 200 | pfc::string8 base, ext;
|
|---|
| 201 | base = p_path;
|
|---|
| 202 | t_size extpos = base.find_last('.');
|
|---|
| 203 | if (extpos >= base.scan_filename()) {
|
|---|
| 204 | // is ext
|
|---|
| 205 | ext.set_string(base + extpos);
|
|---|
| 206 | base.truncate(extpos);
|
|---|
| 207 | } else {
|
|---|
| 208 | ext = "";
|
|---|
| 209 | }
|
|---|
| 210 | m_head.path.reset();
|
|---|
| 211 | m_head.path << base << m_head.suffix << ext;
|
|---|
| 212 | try {
|
|---|
| 213 | open_path_helper(m_head.input, NULL, m_head.path, p_abort, p_from_redirect, p_skip_hints);
|
|---|
| 214 | } catch (exception_io_not_found) {
|
|---|
| 215 | console::formatter() << "loop twofiles: head file not found: \"" << file_path_display(m_head.path) << "\"";
|
|---|
| 216 | return false;
|
|---|
| 217 | }
|
|---|
| 218 | m_body.path.reset();
|
|---|
| 219 | m_body.path << base << m_body.suffix << ext;
|
|---|
| 220 | try {
|
|---|
| 221 | open_path_helper(m_body.input, NULL, m_body.path, p_abort, p_from_redirect, p_skip_hints);
|
|---|
| 222 | } catch (exception_io_not_found) {
|
|---|
| 223 | console::formatter() << "loop twofiles: body file not found: \"" << file_path_display(m_body.path) << "\"";
|
|---|
| 224 | return false;
|
|---|
| 225 | }
|
|---|
| 226 | if (m_head.input.is_empty() || m_body.input.is_empty()) return false;
|
|---|
| 227 | m_points.remove_all();
|
|---|
| 228 | input_loop_event_point_twofiles_eof * point = new service_impl_t<input_loop_event_point_twofiles_eof>();
|
|---|
| 229 | m_points.add_item(point);
|
|---|
| 230 | switch_points(m_points);
|
|---|
| 231 | file_info_impl p_info;
|
|---|
| 232 | m_head.input->get_info(0, p_info, p_abort);
|
|---|
| 233 | m_head.samples = p_info.info_get_length_samples();
|
|---|
| 234 | p_info.reset();
|
|---|
| 235 | m_body.input->get_info(0, p_info, p_abort);
|
|---|
| 236 | m_body.samples = p_info.info_get_length_samples();
|
|---|
| 237 | switch_to(m_head);
|
|---|
| 238 | return true;
|
|---|
| 239 | }
|
|---|
| 240 | virtual void get_info(t_uint32 subsong, file_info & p_info,abort_callback & p_abort) {
|
|---|
| 241 | t_uint32 sample_rate = get_sample_rate();
|
|---|
| 242 | m_head.input->get_info(subsong, p_info, p_abort);
|
|---|
| 243 | pfc::string8 name;
|
|---|
| 244 | name << get_info_prefix() << "head_length";
|
|---|
| 245 | p_info.info_set(name, format_samples_ex(m_head.samples, sample_rate));
|
|---|
| 246 | name.reset();
|
|---|
| 247 | name << get_info_prefix() << "body_length";
|
|---|
| 248 | p_info.info_set(name, format_samples_ex(m_body.samples, sample_rate));
|
|---|
| 249 | p_info.set_length(audio_math::samples_to_time(m_head.samples + m_body.samples, sample_rate));
|
|---|
| 250 | }
|
|---|
| 251 | virtual t_filestats get_file_stats(abort_callback & p_abort) {
|
|---|
| 252 | return merge_filestats(
|
|---|
| 253 | m_head.input->get_file_stats(p_abort),
|
|---|
| 254 | m_body.input->get_file_stats(p_abort),
|
|---|
| 255 | merge_filestats_sum);
|
|---|
| 256 | }
|
|---|
| 257 | void virtual close() {
|
|---|
| 258 | m_head.input.release();
|
|---|
| 259 | m_body.input.release();
|
|---|
| 260 | }
|
|---|
| 261 | void virtual on_idle(abort_callback & p_abort) {
|
|---|
| 262 | m_head.input->on_idle(p_abort);
|
|---|
| 263 | m_body.input->on_idle(p_abort);
|
|---|
| 264 | }
|
|---|
| 265 | virtual bool on_eof_event(abort_callback & p_abort) {
|
|---|
| 266 | switch_to(m_body);
|
|---|
| 267 | if (get_no_looping()) switch_points(input_loop_event_point_list()); // clear event for disable looping
|
|---|
| 268 | raw_seek((t_uint64)0,p_abort);
|
|---|
| 269 | return true;
|
|---|
| 270 | }
|
|---|
| 271 | virtual void seek(double p_seconds,abort_callback & p_abort) {
|
|---|
| 272 | seek(audio_math::time_to_samples(p_seconds, get_sample_rate()),p_abort);
|
|---|
| 273 | }
|
|---|
| 274 | virtual void seek(t_uint64 p_samples,abort_callback & p_abort) {
|
|---|
| 275 | if (p_samples < m_head.samples) {
|
|---|
| 276 | switch_to(m_head);
|
|---|
| 277 | user_seek(p_samples,p_abort);
|
|---|
| 278 | } else {
|
|---|
| 279 | p_samples -= m_head.samples;
|
|---|
| 280 | switch_to(m_body);
|
|---|
| 281 | user_seek(p_samples,p_abort);
|
|---|
| 282 | }
|
|---|
| 283 | }
|
|---|
| 284 | FB2K_MAKE_SERVICE_INTERFACE(input_loop_type_twofiles, input_loop_type);
|
|---|
| 285 | };
|
|---|
| 286 |
|
|---|
| 287 | bool input_loop_event_point_twofiles_eof::process(input_loop_type_base::ptr p_input, abort_callback & p_abort) {
|
|---|
| 288 | input_loop_type_twofiles::ptr p_input_special;
|
|---|
| 289 | if (p_input->service_query_t<input_loop_type_twofiles>(p_input_special)) {
|
|---|
| 290 | return p_input_special->on_eof_event(p_abort);
|
|---|
| 291 | }
|
|---|
| 292 | return false;
|
|---|
| 293 | }
|
|---|
| 294 |
|
|---|
| 295 | static input_loop_type_factory_t<input_loop_type_twofiles> g_input_loop_type_twofiles;
|
|---|
| 296 |
|
|---|
| 297 | class input_loop_type_sampler : public input_loop_type_impl_singlefile_base
|
|---|
| 298 | {
|
|---|
| 299 | private:
|
|---|
| 300 | input_decoder::ptr m_input;
|
|---|
| 301 | input_loop_event_point_list m_points;
|
|---|
| 302 | public:
|
|---|
| 303 | static const char * g_get_name() {return "Wave(RIFF) Sampler";}
|
|---|
| 304 | static const char * g_get_short_name() {return "sampler";}
|
|---|
| 305 | static bool g_is_our_type(const char * type) {return !pfc::stringCompareCaseInsensitive(type, "sampler");}
|
|---|
| 306 | static bool g_is_explicit() {return false;}
|
|---|
| 307 | virtual bool parse(const char * ptr) {
|
|---|
| 308 | return true;
|
|---|
| 309 | }
|
|---|
| 310 | virtual bool open_path_internal(file::ptr p_filehint,const char * path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
|
|---|
| 311 | if (p_filehint.is_empty()) {
|
|---|
| 312 | try {
|
|---|
| 313 | filesystem::g_open_read(p_filehint,path,p_abort);
|
|---|
| 314 | } catch (exception_io_not_found) {
|
|---|
| 315 | return false;
|
|---|
| 316 | }
|
|---|
| 317 | }
|
|---|
| 318 | p_filehint->reopen(p_abort);
|
|---|
| 319 | if (p_filehint->is_remote()) {
|
|---|
| 320 | console::formatter() << "loop sampler: file must be local: \"" << file_path_display(path) << "\"";
|
|---|
| 321 | return false;
|
|---|
| 322 | }
|
|---|
| 323 | pfc::string8 buf;
|
|---|
| 324 | t_uint32 size;
|
|---|
| 325 | p_filehint->read_string_ex(buf, 4, p_abort); // chunkname: RIFF
|
|---|
| 326 | if (!!pfc::strcmp_ex(buf, 4, "RIFF", 4))
|
|---|
| 327 | return false;
|
|---|
| 328 | p_filehint->read_lendian_t(size, p_abort); // chunksize
|
|---|
| 329 | p_filehint->read_string_ex(buf, 4, p_abort); // filetype: WAVE
|
|---|
| 330 | while (!p_filehint->is_eof(p_abort)) {
|
|---|
| 331 | p_filehint->read_string_ex(buf, 4, p_abort); // chunkname
|
|---|
| 332 | p_filehint->read_lendian_t(size, p_abort); // chunksize
|
|---|
| 333 | if (!!pfc::strcmp_ex(buf, 4, "smpl", 4)) {
|
|---|
| 334 | p_filehint->skip(size, p_abort);
|
|---|
| 335 | continue;
|
|---|
| 336 | }
|
|---|
| 337 | stream_reader_limited_ref chunk_reader(p_filehint.get_ptr(), size);
|
|---|
| 338 | // chunk found;
|
|---|
| 339 | /*
|
|---|
| 340 | UnsignedInt('manufacturer'),
|
|---|
| 341 | UnsignedInt('product'),
|
|---|
| 342 | UnsignedInt('sample_period'),
|
|---|
| 343 | UnsignedInt('midi_unity_note'),
|
|---|
| 344 | UnsignedInt('midi_pitch_fraction'),
|
|---|
| 345 | UnsignedInt('smpte_format'),
|
|---|
| 346 | UnsignedInt('smpte_offset'),
|
|---|
| 347 | UnsignedInt('num_sample_loops'),
|
|---|
| 348 | UnsignedInt('sampler_data'),
|
|---|
| 349 | */
|
|---|
| 350 | t_uint32 i;
|
|---|
| 351 | chunk_reader.skip(4 * 7, p_abort);
|
|---|
| 352 | chunk_reader.read_lendian_t(i, p_abort);
|
|---|
| 353 | chunk_reader.skip(4, p_abort); // sampler_data
|
|---|
| 354 | for (; i>0; i--) {
|
|---|
| 355 | /*
|
|---|
| 356 | UnsignedInt('cue_point_id'),
|
|---|
| 357 | UnsignedInt('type'),
|
|---|
| 358 | UnsignedInt('start'),
|
|---|
| 359 | UnsignedInt('end'),
|
|---|
| 360 | UnsignedInt('fraction'),
|
|---|
| 361 | UnsignedInt('playcount'),
|
|---|
| 362 | */
|
|---|
| 363 | input_loop_event_point_simple * point = new service_impl_t<input_loop_event_point_simple>();
|
|---|
| 364 | t_uint32 temp;
|
|---|
| 365 | chunk_reader.read_lendian_t(temp, p_abort); // cue_point_id: ignore
|
|---|
| 366 | chunk_reader.read_lendian_t(temp, p_abort); // type: currently known: 0 only
|
|---|
| 367 | if (temp != 0) {
|
|---|
| 368 | pfc::string8 errmsg;
|
|---|
| 369 | errmsg << "Unknown sampleloop type: " << temp;
|
|---|
| 370 | throw exception_io_data(errmsg);
|
|---|
| 371 | }
|
|---|
| 372 | chunk_reader.read_lendian_t(temp, p_abort); // start
|
|---|
| 373 | point->to = temp;
|
|---|
| 374 | chunk_reader.read_lendian_t(temp, p_abort); // end
|
|---|
| 375 | point->from = temp;
|
|---|
| 376 | chunk_reader.read_lendian_t(temp, p_abort); // fraction
|
|---|
| 377 | if (temp != 0) {
|
|---|
| 378 | pfc::string8 errmsg;
|
|---|
| 379 | errmsg << "Unknown sampleloop fraction: " << temp;
|
|---|
| 380 | throw exception_io_data(errmsg);
|
|---|
| 381 | }
|
|---|
| 382 | chunk_reader.read_lendian_t(temp, p_abort); // playcount
|
|---|
| 383 | point->maxrepeats = temp;
|
|---|
| 384 | m_points.add_item(point);
|
|---|
| 385 | }
|
|---|
| 386 | }
|
|---|
| 387 | if (m_points.get_count() == 0)
|
|---|
| 388 | return false;
|
|---|
| 389 | try {
|
|---|
| 390 | open_path_helper(m_input, p_filehint, path, p_abort, p_from_redirect,p_skip_hints);
|
|---|
| 391 | } catch (exception_io_not_found) {
|
|---|
| 392 | return false;
|
|---|
| 393 | }
|
|---|
| 394 | switch_input(m_input);
|
|---|
| 395 | switch_points(m_points);
|
|---|
| 396 | return true;
|
|---|
| 397 | }
|
|---|
| 398 | virtual void get_info(t_uint32 subsong, file_info & p_info,abort_callback & p_abort) {
|
|---|
| 399 | get_input()->get_info(subsong, p_info, p_abort);
|
|---|
| 400 | get_info_for_points(p_info, m_points, get_info_prefix(), get_sample_rate());
|
|---|
| 401 | }
|
|---|
| 402 | };
|
|---|
| 403 |
|
|---|
| 404 | static input_loop_type_factory_t<input_loop_type_sampler> g_input_loop_type_sampler;
|
|---|
| 405 |
|
|---|
| 406 | #pragma region GUIDs
|
|---|
| 407 | // {C9E7AF50-FDF8-4a2f-99A6-8DE4D2B49D0C}
|
|---|
| 408 | FOOGUIDDECL const GUID input_loop_type::class_guid =
|
|---|
| 409 | { 0xc9e7af50, 0xfdf8, 0x4a2f, { 0x99, 0xa6, 0x8d, 0xe4, 0xd2, 0xb4, 0x9d, 0xc } };
|
|---|
| 410 |
|
|---|
| 411 | // {CA8E32C1-1A2D-4679-87AB-03292A97D890}
|
|---|
| 412 | FOOGUIDDECL const GUID input_loop_type_base::class_guid =
|
|---|
| 413 | { 0xca8e32c1, 0x1a2d, 0x4679, { 0x87, 0xab, 0x3, 0x29, 0x2a, 0x97, 0xd8, 0x90 } };
|
|---|
| 414 |
|
|---|
| 415 | // {2910A6A6-A12B-414f-971B-90A65F79439B}
|
|---|
| 416 | FOOGUIDDECL const GUID input_loop_event_point::class_guid =
|
|---|
| 417 | { 0x2910a6a6, 0xa12b, 0x414f, { 0x97, 0x1b, 0x90, 0xa6, 0x5f, 0x79, 0x43, 0x9b } };
|
|---|
| 418 |
|
|---|
| 419 | //// {CFBEBA19-9B94-46b0-AA21-D2906B139EDE}
|
|---|
| 420 | FOOGUIDDECL const GUID input_loop_type_twofiles::class_guid =
|
|---|
| 421 | { 0xcfbeba19, 0x9b94, 0x46b0, { 0xaa, 0x21, 0xd2, 0x90, 0x6b, 0x13, 0x9e, 0xde } };
|
|---|
| 422 |
|
|---|
| 423 | //// {566BCC79-7370-48c0-A7CB-5E47C4C17A86}
|
|---|
| 424 | FOOGUIDDECL const GUID input_loop_type_entry::class_guid =
|
|---|
| 425 | { 0x566bcc79, 0x7370, 0x48c0, { 0xa7, 0xcb, 0x5e, 0x47, 0xc4, 0xc1, 0x7a, 0x86 } };
|
|---|
| 426 |
|
|---|
| 427 | #pragma endregion
|
|---|
| 428 |
|
|---|