|
1
|
1 #include "StdAfx.h"
|
|
|
2 #include "cuesheet_index_list.h"
|
|
|
3
|
|
|
4 #include "cue_parser.h" // exception_bad_cuesheet
|
|
|
5
|
|
|
6 bool t_cuesheet_index_list::is_valid() const {
|
|
|
7 if (m_positions[1] < m_positions[0]) return false;
|
|
|
8 for(t_size n = 2; n < count && m_positions[n] > 0; n++) {
|
|
|
9 if (m_positions[n] < m_positions[n-1]) return false;
|
|
|
10 }
|
|
|
11 return true;
|
|
|
12 }
|
|
|
13
|
|
|
14 void t_cuesheet_index_list::to_infos(file_info & p_out) const
|
|
|
15 {
|
|
|
16 double base = m_positions[1];
|
|
|
17
|
|
|
18 if (base > 0) {
|
|
|
19 p_out.info_set("referenced_offset",cuesheet_format_index_time(base));
|
|
|
20 }
|
|
|
21
|
|
|
22 if (m_positions[0] < base)
|
|
|
23 p_out.info_set("pregap",cuesheet_format_index_time(base - m_positions[0]));
|
|
|
24 else
|
|
|
25 p_out.info_remove("pregap");
|
|
|
26
|
|
|
27 p_out.info_remove("index 00");
|
|
|
28 p_out.info_remove("index 01");
|
|
|
29
|
|
|
30 for(unsigned n=2;n<count;n++)
|
|
|
31 {
|
|
|
32 char namebuffer[16];
|
|
|
33 snprintf(namebuffer, std::size(namebuffer), "index %02u",n);
|
|
|
34 double position = m_positions[n] - base;
|
|
|
35 if (position > 0)
|
|
|
36 p_out.info_set(namebuffer,cuesheet_format_index_time(position));
|
|
|
37 else
|
|
|
38 p_out.info_remove(namebuffer);
|
|
|
39 }
|
|
|
40 }
|
|
|
41
|
|
|
42 static bool parse_value(const char * p_name,double & p_out)
|
|
|
43 {
|
|
|
44 if (p_name == NULL) return false;
|
|
|
45 try {
|
|
|
46 p_out = cuesheet_parse_index_time_e(p_name,strlen(p_name));
|
|
|
47 } catch(std::exception const &) {return false;}
|
|
|
48 return true;
|
|
|
49 }
|
|
|
50
|
|
|
51 bool t_cuesheet_index_list::from_infos(file_info const & p_in,double p_base)
|
|
|
52 {
|
|
|
53 double pregap;
|
|
|
54 bool found = false;
|
|
|
55 if (!parse_value(p_in.info_get("pregap"),pregap)) pregap = 0;
|
|
|
56 else found = true;
|
|
|
57 m_positions[0] = p_base - pregap;
|
|
|
58 m_positions[1] = p_base;
|
|
|
59 for(unsigned n=2;n<count;n++)
|
|
|
60 {
|
|
|
61 char namebuffer[16];
|
|
|
62 snprintf(namebuffer, std::size(namebuffer),"index %02u",n);
|
|
|
63 double temp;
|
|
|
64 if (parse_value(p_in.info_get(namebuffer),temp)) {
|
|
|
65 m_positions[n] = temp + p_base; found = true;
|
|
|
66 } else {
|
|
|
67 m_positions[n] = 0;
|
|
|
68 }
|
|
|
69 }
|
|
|
70 return found;
|
|
|
71 }
|
|
|
72
|
|
|
73 bool t_cuesheet_index_list::is_empty() const {
|
|
|
74 for(unsigned n=0;n<count;n++) if (m_positions[n] != m_positions[1]) return false;
|
|
|
75 return true;
|
|
|
76 }
|
|
|
77
|
|
|
78
|
|
|
79
|
|
|
80
|
|
|
81
|
|
|
82
|
|
|
83 cuesheet_format_index_time::cuesheet_format_index_time(double p_time)
|
|
|
84 {
|
|
|
85 t_uint64 ticks = audio_math::time_to_samples(p_time,75);
|
|
|
86 t_uint64 seconds = ticks / 75; ticks %= 75;
|
|
|
87 t_uint64 minutes = seconds / 60; seconds %= 60;
|
|
|
88 m_buffer << pfc::format_uint(minutes,2) << ":" << pfc::format_uint(seconds,2) << ":" << pfc::format_uint(ticks,2);
|
|
|
89 }
|
|
|
90
|
|
|
91 double cuesheet_parse_index_time_e(const char * p_string,t_size p_length)
|
|
|
92 {
|
|
|
93 return (double) cuesheet_parse_index_time_ticks_e(p_string,p_length) / 75.0;
|
|
|
94 }
|
|
|
95
|
|
|
96 unsigned cuesheet_parse_index_time_ticks_e(const char * p_string,t_size p_length)
|
|
|
97 {
|
|
|
98 p_length = pfc::strlen_max(p_string,p_length);
|
|
|
99 t_size ptr = 0;
|
|
|
100 t_size splitmarks[2];
|
|
|
101 t_size splitptr = 0;
|
|
|
102 for(ptr=0;ptr<p_length;ptr++)
|
|
|
103 {
|
|
|
104 if (p_string[ptr] == ':')
|
|
|
105 {
|
|
|
106 if (splitptr >= 2)
|
|
|
107 pfc::throw_exception_with_message< cue_parser::exception_bad_cuesheet >("invalid INDEX time syntax");
|
|
|
108 splitmarks[splitptr++] = ptr;
|
|
|
109 }
|
|
|
110 else if (!pfc::char_is_numeric(p_string[ptr]))
|
|
|
111 pfc::throw_exception_with_message< cue_parser::exception_bad_cuesheet >("invalid INDEX time syntax");
|
|
|
112 }
|
|
|
113
|
|
|
114 t_size minutes_base = 0, minutes_length = 0, seconds_base = 0, seconds_length = 0, frames_base = 0, frames_length = 0;
|
|
|
115
|
|
|
116 switch(splitptr)
|
|
|
117 {
|
|
|
118 case 0:
|
|
|
119 frames_base = 0;
|
|
|
120 frames_length = p_length;
|
|
|
121 break;
|
|
|
122 case 1:
|
|
|
123 seconds_base = 0;
|
|
|
124 seconds_length = splitmarks[0];
|
|
|
125 frames_base = splitmarks[0] + 1;
|
|
|
126 frames_length = p_length - frames_base;
|
|
|
127 break;
|
|
|
128 case 2:
|
|
|
129 minutes_base = 0;
|
|
|
130 minutes_length = splitmarks[0];
|
|
|
131 seconds_base = splitmarks[0] + 1;
|
|
|
132 seconds_length = splitmarks[1] - seconds_base;
|
|
|
133 frames_base = splitmarks[1] + 1;
|
|
|
134 frames_length = p_length - frames_base;
|
|
|
135 break;
|
|
|
136 }
|
|
|
137
|
|
|
138 unsigned ret = 0;
|
|
|
139
|
|
|
140 if (frames_length > 0) ret += pfc::atoui_ex(p_string + frames_base,frames_length);
|
|
|
141 if (seconds_length > 0) ret += 75 * pfc::atoui_ex(p_string + seconds_base,seconds_length);
|
|
|
142 if (minutes_length > 0) ret += 60 * 75 * pfc::atoui_ex(p_string + minutes_base,minutes_length);
|
|
|
143
|
|
|
144 return ret;
|
|
|
145 }
|