1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Legacy.cpp
6
7 Dominic Mazzoni
8
9 *******************************************************************//*!
10
11 \file Legacy.cpp
12 \brief Converts old Audacity file types. Implements
13 AutoRollbackRenamer.
14
15 These routines convert Audacity project files from the
16 0.98...1.0 format into an XML format that's compatible with
17 Audacity 1.2.0 and newer.
18
19 *//****************************************************************//**
20
21 \class AutoRollbackRenamer
22 \brief AutoRollbackRenamer handles the renaming of files
23 which is needed when producing a NEW version of a file which may fail.
24 On failure the old version is put back in place.
25
26 *//*******************************************************************/
27
28
29
30 #include "Legacy.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <wx/defs.h>
37 #include <wx/ffile.h>
38 #include <wx/filefn.h>
39 #include <wx/intl.h>
40 #include <wx/string.h>
41 #include <wx/textfile.h>
42
43 #include "widgets/AudacityMessageBox.h"
44 #include "XMLWriter.h"
45
ConvertLegacyTrack(wxTextFile * f,XMLFileWriter & xmlFile)46 static bool ConvertLegacyTrack(wxTextFile *f, XMLFileWriter &xmlFile)
47 // may throw
48 {
49 wxString line;
50 wxString kind;
51
52 kind = (*f)[f->GetCurrentLine()];
53
54 if (kind == wxT("WaveTrack")) {
55 xmlFile.StartTag(wxT("wavetrack"));
56 xmlFile.WriteAttr(wxT("name"), f->GetNextLine());
57
58 wxString channel = f->GetNextLine();
59 if (channel == wxT("left")) {
60 xmlFile.WriteAttr(wxT("channel"), 0);
61 line = f->GetNextLine();
62 }
63 else if (channel == wxT("right")) {
64 xmlFile.WriteAttr(wxT("channel"), 1);
65 line = f->GetNextLine();
66 }
67 else if (channel == wxT("mono")) {
68 xmlFile.WriteAttr(wxT("channel"), 2);
69 line = f->GetNextLine();
70 }
71 else {
72 xmlFile.WriteAttr(wxT("channel"), 2);
73 line = channel;
74 }
75
76 if (line == wxT("linked")) {
77 xmlFile.WriteAttr(wxT("linked"), 1);
78 line = f->GetNextLine();
79 }
80
81 if (line != wxT("offset"))
82 return false;
83 xmlFile.WriteAttr(wxT("offset"), f->GetNextLine());
84
85 long envLen;
86
87 if (f->GetNextLine() != wxT("EnvNumPoints"))
88 return false;
89 line = f->GetNextLine();
90 line.ToLong(&envLen);
91 if (envLen < 0 || envLen > 10000)
92 return false;
93
94 size_t envStart = f->GetCurrentLine();
95 if (f->GetLineCount() < envStart+(2*envLen)+1)
96 return false;
97
98 f->GoToLine(envStart+(2*envLen));
99 if (f->GetNextLine() != wxT("EnvEnd"))
100 return false;
101 if (f->GetNextLine() != wxT("numSamples"))
102 return false;
103
104 wxString numSamples = f->GetNextLine();
105
106 if (f->GetNextLine() != wxT("rate"))
107 return false;
108
109 xmlFile.WriteAttr(wxT("rate"), f->GetNextLine());
110
111 if (envLen > 0) {
112 xmlFile.StartTag(wxT("envelope"));
113 xmlFile.WriteAttr(wxT("numpoints"), envLen);
114
115 long i;
116 for(i=0; i<envLen; i++) {
117 xmlFile.StartTag(wxT("controlpoint"));
118 xmlFile.WriteAttr(wxT("t"), f->GetLine(envStart + 2*i + 1));
119 xmlFile.WriteAttr(wxT("val"), f->GetLine(envStart + 2*i + 2));
120 xmlFile.EndTag(wxT("controlpoint"));
121 }
122
123 xmlFile.EndTag(wxT("envelope"));
124 }
125
126 if (f->GetNextLine() != wxT("numBlocks"))
127 return false;
128 long numBlocks;
129 line = f->GetNextLine();
130 line.ToLong(&numBlocks);
131
132 if (numBlocks < 0 || numBlocks > 131072)
133 return false;
134
135 xmlFile.StartTag(wxT("sequence"));
136 xmlFile.WriteAttr(wxT("maxsamples"), 524288);
137 xmlFile.WriteAttr(wxT("sampleformat"), 131073);
138 xmlFile.WriteAttr(wxT("numsamples"), numSamples);
139
140 long b;
141 for(b=0; b<numBlocks; b++) {
142 wxString start;
143 wxString len;
144 wxString name;
145
146 if (f->GetNextLine() != wxT("Block start"))
147 return false;
148 start = f->GetNextLine();
149 if (f->GetNextLine() != wxT("Block len"))
150 return false;
151 len = f->GetNextLine();
152 if (f->GetNextLine() != wxT("Block info"))
153 return false;
154 name = f->GetNextLine();
155
156 xmlFile.StartTag(wxT("waveblock"));
157 xmlFile.WriteAttr(wxT("start"), start);
158
159 xmlFile.StartTag(wxT("legacyblockfile"));
160 if (name == wxT("Alias")) {
161 wxString aliasPath = f->GetNextLine();
162 wxString localLen = f->GetNextLine();
163 wxString aliasStart = f->GetNextLine();
164 wxString aliasLen = f->GetNextLine();
165 wxString aliasChannel = f->GetNextLine();
166 wxString localName = f->GetNextLine();
167
168 xmlFile.WriteAttr(wxT("name"), localName);
169 xmlFile.WriteAttr(wxT("alias"), 1);
170 xmlFile.WriteAttr(wxT("aliaspath"), aliasPath);
171
172 // This was written but not read again?
173 xmlFile.WriteAttr(wxT("aliasstart"), aliasStart);
174
175 xmlFile.WriteAttr(wxT("aliaslen"), aliasLen);
176 xmlFile.WriteAttr(wxT("aliaschannel"), aliasChannel);
177 xmlFile.WriteAttr(wxT("summarylen"), localLen);
178 xmlFile.WriteAttr(wxT("norms"), 1);
179 }
180 else {
181 xmlFile.WriteAttr(wxT("name"), name);
182 xmlFile.WriteAttr(wxT("len"), len);
183 xmlFile.WriteAttr(wxT("summarylen"), 8244);
184 xmlFile.WriteAttr(wxT("norms"), 1);
185 }
186 xmlFile.EndTag(wxT("legacyblockfile"));
187
188 xmlFile.EndTag(wxT("waveblock"));
189 }
190
191 xmlFile.EndTag(wxT("sequence"));
192 xmlFile.EndTag(wxT("wavetrack"));
193
194 return true;
195 }
196 else if (kind == wxT("LabelTrack")) {
197 line = f->GetNextLine();
198 if (line != wxT("NumMLabels"))
199 return false;
200
201 long numLabels, l;
202
203 line = f->GetNextLine();
204 line.ToLong(&numLabels);
205 if (numLabels < 0 || numLabels > 1000000)
206 return false;
207
208 xmlFile.StartTag(wxT("labeltrack"));
209 xmlFile.WriteAttr(wxT("name"), wxT("Labels"));
210 xmlFile.WriteAttr(wxT("numlabels"), numLabels);
211
212 for(l=0; l<numLabels; l++) {
213 wxString t, title;
214
215 t = f->GetNextLine();
216 title = f->GetNextLine();
217
218 xmlFile.StartTag(wxT("label"));
219 xmlFile.WriteAttr(wxT("t"), t);
220 xmlFile.WriteAttr(wxT("title"), title);
221 xmlFile.EndTag(wxT("label"));
222 }
223
224 xmlFile.EndTag(wxT("labeltrack"));
225
226 line = f->GetNextLine();
227 if (line != wxT("MLabelsEnd"))
228 return false;
229
230 return true;
231 }
232 else if (kind == wxT("NoteTrack")) {
233 // Just skip over it - they didn't even work in version 1.0!
234
235 do {
236 line = f->GetNextLine();
237 if (line == wxT("WaveTrack") ||
238 line == wxT("NoteTrack") ||
239 line == wxT("LabelTrack") ||
240 line == wxT("EndTracks")) {
241 f->GoToLine(f->GetCurrentLine()-1);
242 return true;
243 }
244 } while (f->GetCurrentLine() < f->GetLineCount());
245
246 return false;
247 }
248 else
249 return false;
250 }
251
ConvertLegacyProjectFile(const wxFileName & filename)252 bool ConvertLegacyProjectFile(const wxFileName &filename)
253 {
254 wxTextFile f;
255
256 const wxString name = filename.GetFullPath();
257 f.Open( name );
258 if (!f.IsOpened())
259 return false;
260
261 return GuardedCall< bool >( [&] {
262 XMLFileWriter xmlFile{ name, XO("Error Converting Legacy Project File") };
263
264 xmlFile.Write(wxT("<?xml version=\"1.0\"?>\n"));
265
266 wxString label;
267 wxString value;
268
269 if (f.GetFirstLine() != wxT("AudacityProject"))
270 return false;
271 if (f.GetNextLine() != wxT("Version"))
272 return false;
273 if (f.GetNextLine() != wxT("0.95"))
274 return false;
275 if (f.GetNextLine() != wxT("projName"))
276 return false;
277
278 xmlFile.StartTag(wxT("audacityproject"));
279 xmlFile.WriteAttr(wxT("projname"), f.GetNextLine());
280 xmlFile.WriteAttr(wxT("version"), wxT("1.1.0"));
281 xmlFile.WriteAttr(wxT("audacityversion"),AUDACITY_VERSION_STRING);
282
283 label = f.GetNextLine();
284 while (label != wxT("BeginTracks")) {
285 xmlFile.WriteAttr(label, f.GetNextLine());
286 label = f.GetNextLine();
287 }
288
289 label = f.GetNextLine();
290 while (label != wxT("EndTracks")) {
291 bool success = ConvertLegacyTrack(&f, xmlFile);
292 if (!success)
293 return false;
294 label = f.GetNextLine();
295 }
296
297 // Close original before Commit() tries to overwrite it.
298 f.Close();
299
300 xmlFile.EndTag(wxT("audacityproject"));
301 xmlFile.Commit();
302
303 ::AudacityMessageBox(
304 XO(
305 "Converted a 1.0 project file to the new format.\nThe old file has been saved as '%s'")
306 .Format( xmlFile.GetBackupName() ),
307 XO("Opening Audacity Project"));
308
309 return true;
310 } );
311 }
312