foobar2000 SDK  2015-08-03
cue_creator.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
3 
4 namespace {
5 
6  class format_meta
7  {
8  public:
9  format_meta(const file_info & p_source,const char * p_name,bool p_allow_space = true)
10  {
11  p_source.meta_format(p_name,m_buffer);
12  m_buffer.replace_byte('\"','\'');
13  uReplaceString(m_buffer,pfc::string8(m_buffer),pfc_infinite,"\x0d\x0a",2,"\\",1,false);
14  if (!p_allow_space) m_buffer.replace_byte(' ','_');
15  m_buffer.replace_nontext_chars();
16  }
17  inline operator const char*() const {return m_buffer;}
18  private:
19  pfc::string8_fastalloc m_buffer;
20  };
21 }
22 
23 static bool is_meta_same_everywhere(const cue_creator::t_entry_list & p_list,const char * p_meta)
24 {
25  pfc::string8_fastalloc reference,temp;
26 
28  iter = p_list.first();
29  if (!iter.is_valid()) return false;
30  if (!iter->m_infos.meta_format(p_meta,reference)) return false;
31  for(;iter.is_valid();++iter)
32  {
33  if (!iter->m_infos.meta_format(p_meta,temp)) return false;
34  if (strcmp(temp,reference)!=0) return false;
35  }
36  return true;
37 }
38 
39 static const char g_eol[] = "\r\n";
40 
41 
42 namespace cue_creator
43 {
44  void create(pfc::string_formatter & p_out,const t_entry_list & p_data)
45  {
46  if (p_data.get_count() == 0) return;
47  bool album_artist_global = is_meta_same_everywhere(p_data,"album artist"),
48  artist_global = is_meta_same_everywhere(p_data,"artist"),
49  album_global = is_meta_same_everywhere(p_data,"album"),
50  genre_global = is_meta_same_everywhere(p_data,"genre"),
51  date_global = is_meta_same_everywhere(p_data,"date"),
52  discid_global = is_meta_same_everywhere(p_data,"discid"),
53  comment_global = is_meta_same_everywhere(p_data,"comment"),
54  catalog_global = is_meta_same_everywhere(p_data,"catalog"),
55  songwriter_global = is_meta_same_everywhere(p_data,"songwriter");
56 
57  if (genre_global) {
58  p_out << "REM GENRE " << format_meta(p_data.first()->m_infos,"genre") << g_eol;
59  }
60  if (date_global) {
61  p_out << "REM DATE " << format_meta(p_data.first()->m_infos,"date") << g_eol;
62  }
63  if (discid_global) {
64  p_out << "REM DISCID " << format_meta(p_data.first()->m_infos,"discid") << g_eol;
65  }
66  if (comment_global) {
67  p_out << "REM COMMENT " << format_meta(p_data.first()->m_infos,"comment") << g_eol;
68  }
69  if (catalog_global) {
70  p_out << "CATALOG " << format_meta(p_data.first()->m_infos,"catalog") << g_eol;
71  }
72  if (songwriter_global) {
73  p_out << "SONGWRITER \"" << format_meta(p_data.first()->m_infos,"songwriter") << "\"" << g_eol;
74  }
75 
76  if (album_artist_global)
77  {
78  p_out << "PERFORMER \"" << format_meta(p_data.first()->m_infos,"album artist") << "\"" << g_eol;
79  artist_global = false;
80  }
81  else if (artist_global)
82  {
83  p_out << "PERFORMER \"" << format_meta(p_data.first()->m_infos,"artist") << "\"" << g_eol;
84  }
85  if (album_global)
86  {
87  p_out << "TITLE \"" << format_meta(p_data.first()->m_infos,"album") << "\"" << g_eol;
88  }
89 
90  {
92  replaygain_info rg = p_data.first()->m_infos.get_replaygain();
93  if (rg.format_album_gain(rgbuffer))
94  p_out << "REM REPLAYGAIN_ALBUM_GAIN " << rgbuffer << g_eol;
95  if (rg.format_album_peak(rgbuffer))
96  p_out << "REM REPLAYGAIN_ALBUM_PEAK " << rgbuffer << g_eol;
97  }
98 
99  pfc::string8 last_file;
100 
101  for(t_entry_list::const_iterator iter = p_data.first();iter.is_valid();++iter)
102  {
103  if (strcmp(last_file,iter->m_file) != 0)
104  {
105  p_out << "FILE \"" << iter->m_file << "\" WAVE" << g_eol;
106  last_file = iter->m_file;
107  }
108 
109  p_out << " TRACK " << pfc::format_int(iter->m_track_number,2) << " AUDIO" << g_eol;
110 
111  if (iter->m_infos.meta_find("title") != pfc_infinite)
112  p_out << " TITLE \"" << format_meta(iter->m_infos,"title") << "\"" << g_eol;
113 
114  if (!artist_global && iter->m_infos.meta_find("artist") != pfc_infinite)
115  p_out << " PERFORMER \"" << format_meta(iter->m_infos,"artist") << "\"" << g_eol;
116 
117  if (!songwriter_global && iter->m_infos.meta_find("songwriter") != pfc_infinite) {
118  p_out << " SONGWRITER \"" << format_meta(iter->m_infos,"songwriter") << "\"" << g_eol;
119  }
120 
121  if (iter->m_infos.meta_find("isrc") != pfc_infinite) {
122  p_out << " ISRC " << format_meta(iter->m_infos,"isrc") << g_eol;
123  }
124 
125  if (!date_global && iter->m_infos.meta_find("date") != pfc_infinite) {
126  p_out << " REM DATE " << format_meta(iter->m_infos,"date") << g_eol;
127  }
128 
129 
130 
131  {
133  replaygain_info rg = iter->m_infos.get_replaygain();
134  if (rg.format_track_gain(rgbuffer))
135  p_out << " REM REPLAYGAIN_TRACK_GAIN " << rgbuffer << g_eol;
136  if (rg.format_track_peak(rgbuffer))
137  p_out << " REM REPLAYGAIN_TRACK_PEAK " << rgbuffer << g_eol;
138  }
139 
140  if (!iter->m_flags.is_empty()) {
141  p_out << " FLAGS " << iter->m_flags << g_eol;
142  }
143 
144  if (iter->m_index_list.m_positions[0] < iter->m_index_list.m_positions[1])
145  {
146  if (iter->m_index_list.m_positions[0] < 0)
147  p_out << " PREGAP " << cuesheet_format_index_time(iter->m_index_list.m_positions[1] - iter->m_index_list.m_positions[0]) << g_eol;
148  else
149  p_out << " INDEX 00 " << cuesheet_format_index_time(iter->m_index_list.m_positions[0]) << g_eol;
150  }
151 
152  p_out << " INDEX 01 " << cuesheet_format_index_time(iter->m_index_list.m_positions[1]) << g_eol;
153 
154  for(unsigned n=2;n<t_cuesheet_index_list::count && iter->m_index_list.m_positions[n] > 0;n++)
155  {
156  p_out << " INDEX " << pfc::format_uint(n,2) << " " << cuesheet_format_index_time(iter->m_index_list.m_positions[n]) << g_eol;
157  }
158 
159  // p_out << " INDEX 01 " << cuesheet_format_index_time(iter->m_offset) << g_eol;
160  }
161  }
162 
163 
164  void t_entry::set_simple_index(double p_time)
165  {
166  m_index_list.reset();
167  m_index_list.m_positions[0] = m_index_list.m_positions[1] = p_time;
168  }
169  void t_entry::set_index01(double index0, double index1) {
170  PFC_ASSERT( index0 <= index1 );
171  m_index_list.reset();
172  m_index_list.m_positions[0] = index0;
173  m_index_list.m_positions[1] = index1;
174  }
175 
176 }
177 
static const char g_eol[]
Definition: cue_creator.cpp:39
bool format_track_gain(char p_buffer[text_buffer_size]) const
Definition: file_info.h:16
Differences between chain_list_v2_t<> and old chain_list_t<>: Iterators pointing to removed items as...
Definition: chain_list_v2.h:26
bool is_valid() const
Definition: iterators.h:24
bool format_album_peak(char p_buffer[text_buffer_size]) const
Definition: file_info.h:17
Structure containing ReplayGain scan results from some playable object, also providing various helper...
Definition: file_info.h:2
t_size get_count() const
Definition: chain_list_v2.h:61
Main interface class for information about some playable object.
Definition: file_info.h:73
bool format_track_peak(char p_buffer[text_buffer_size]) const
Definition: file_info.h:18
void create(pfc::string_formatter &p_out, const t_entry_list &p_data)
Definition: cue_creator.cpp:44
bool format_album_gain(char p_buffer[text_buffer_size]) const
Definition: file_info.h:15
bool meta_format(const char *p_name, pfc::string_base &p_out, const char *separator=", ") const
Definition: file_info.cpp:387
t_size uReplaceString(pfc::string_base &out, const char *src, t_size src_len, const char *s1, t_size len1, const char *s2, t_size len2, bool casesens)
Definition: shared.h:388
static bool is_meta_same_everywhere(const cue_creator::t_entry_list &p_list, const char *p_meta)
Definition: cue_creator.cpp:23
string8_t< pfc::alloc_fast_aggressive > string8_fastalloc
Definition: string_base.h:436
char t_text_buffer[text_buffer_size]
Definition: file_info.h:8