Files
foobar2000-sdk/foobar2000/helpers/cuesheet_index_list.cpp
2021-12-14 00:28:25 -07:00

146 lines
3.7 KiB
C++

#include "stdafx.h"
#include "cuesheet_index_list.h"
#ifndef _MSC_VER
#define sprintf_s sprintf
#endif
bool t_cuesheet_index_list::is_valid() const {
if (m_positions[1] < m_positions[0]) return false;
for(t_size n = 2; n < count && m_positions[n] > 0; n++) {
if (m_positions[n] < m_positions[n-1]) return false;
}
return true;
}
void t_cuesheet_index_list::to_infos(file_info & p_out) const
{
double base = m_positions[1];
if (base > 0) {
p_out.info_set("referenced_offset",cuesheet_format_index_time(base));
}
if (m_positions[0] < base)
p_out.info_set("pregap",cuesheet_format_index_time(base - m_positions[0]));
else
p_out.info_remove("pregap");
p_out.info_remove("index 00");
p_out.info_remove("index 01");
for(unsigned n=2;n<count;n++)
{
char namebuffer[16];
sprintf_s(namebuffer,"index %02u",n);
double position = m_positions[n] - base;
if (position > 0)
p_out.info_set(namebuffer,cuesheet_format_index_time(position));
else
p_out.info_remove(namebuffer);
}
}
static bool parse_value(const char * p_name,double & p_out)
{
if (p_name == NULL) return false;
try {
p_out = cuesheet_parse_index_time_e(p_name,strlen(p_name));
} catch(std::exception const &) {return false;}
return true;
}
bool t_cuesheet_index_list::from_infos(file_info const & p_in,double p_base)
{
double pregap;
bool found = false;
if (!parse_value(p_in.info_get("pregap"),pregap)) pregap = 0;
else found = true;
m_positions[0] = p_base - pregap;
m_positions[1] = p_base;
for(unsigned n=2;n<count;n++)
{
char namebuffer[16];
sprintf_s(namebuffer,"index %02u",n);
double temp;
if (parse_value(p_in.info_get(namebuffer),temp)) {
m_positions[n] = temp + p_base; found = true;
} else {
m_positions[n] = 0;
}
}
return found;
}
bool t_cuesheet_index_list::is_empty() const {
for(unsigned n=0;n<count;n++) if (m_positions[n] != m_positions[1]) return false;
return true;
}
cuesheet_format_index_time::cuesheet_format_index_time(double p_time)
{
t_uint64 ticks = audio_math::time_to_samples(p_time,75);
t_uint64 seconds = ticks / 75; ticks %= 75;
t_uint64 minutes = seconds / 60; seconds %= 60;
m_buffer << pfc::format_uint(minutes,2) << ":" << pfc::format_uint(seconds,2) << ":" << pfc::format_uint(ticks,2);
}
double cuesheet_parse_index_time_e(const char * p_string,t_size p_length)
{
return (double) cuesheet_parse_index_time_ticks_e(p_string,p_length) / 75.0;
}
unsigned cuesheet_parse_index_time_ticks_e(const char * p_string,t_size p_length)
{
p_length = pfc::strlen_max(p_string,p_length);
t_size ptr = 0;
t_size splitmarks[2];
t_size splitptr = 0;
for(ptr=0;ptr<p_length;ptr++)
{
if (p_string[ptr] == ':')
{
if (splitptr >= 2) throw std::runtime_error("invalid INDEX time syntax");
splitmarks[splitptr++] = ptr;
}
else if (!pfc::char_is_numeric(p_string[ptr])) throw std::runtime_error("invalid INDEX time syntax");
}
t_size minutes_base = 0, minutes_length = 0, seconds_base = 0, seconds_length = 0, frames_base = 0, frames_length = 0;
switch(splitptr)
{
case 0:
frames_base = 0;
frames_length = p_length;
break;
case 1:
seconds_base = 0;
seconds_length = splitmarks[0];
frames_base = splitmarks[0] + 1;
frames_length = p_length - frames_base;
break;
case 2:
minutes_base = 0;
minutes_length = splitmarks[0];
seconds_base = splitmarks[0] + 1;
seconds_length = splitmarks[1] - seconds_base;
frames_base = splitmarks[1] + 1;
frames_length = p_length - frames_base;
break;
}
unsigned ret = 0;
if (frames_length > 0) ret += pfc::atoui_ex(p_string + frames_base,frames_length);
if (seconds_length > 0) ret += 75 * pfc::atoui_ex(p_string + seconds_base,seconds_length);
if (minutes_length > 0) ret += 60 * 75 * pfc::atoui_ex(p_string + minutes_base,minutes_length);
return ret;
}