comparison data/fileio/WavFileWriter.cpp @ 674:920e3880f7b4

* Add TempWriteFile abstraction, use it when exporting audio to avoid clobbering existing file before export is complete
author Chris Cannam
date Tue, 29 Mar 2011 17:30:23 +0100
parents 5877d68815c7
children bcca512445f3 06f13a3b9e9e
comparison
equal deleted inserted replaced
673:a1ae2c1f80ab 674:920e3880f7b4
15 15
16 #include "WavFileWriter.h" 16 #include "WavFileWriter.h"
17 17
18 #include "model/DenseTimeValueModel.h" 18 #include "model/DenseTimeValueModel.h"
19 #include "base/Selection.h" 19 #include "base/Selection.h"
20 #include "base/TempWriteFile.h"
21 #include "base/Exceptions.h"
20 22
21 #include <QFileInfo> 23 #include <QFileInfo>
22 24
23 #include <iostream> 25 #include <iostream>
24 26
26 size_t sampleRate, 28 size_t sampleRate,
27 size_t channels) : 29 size_t channels) :
28 m_path(path), 30 m_path(path),
29 m_sampleRate(sampleRate), 31 m_sampleRate(sampleRate),
30 m_channels(channels), 32 m_channels(channels),
33 m_temp(0),
31 m_file(0) 34 m_file(0)
32 { 35 {
33 SF_INFO fileInfo; 36 SF_INFO fileInfo;
34 fileInfo.samplerate = m_sampleRate; 37 fileInfo.samplerate = m_sampleRate;
35 fileInfo.channels = m_channels; 38 fileInfo.channels = m_channels;
36 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; 39 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
37 40
38 m_file = sf_open(m_path.toLocal8Bit(), SFM_WRITE, &fileInfo); 41 try {
39 if (!m_file) { 42 m_temp = new TempWriteFile(m_path);
40 std::cerr << "WavFileWriter: Failed to open file (" 43 m_file = sf_open(m_temp->getTemporaryFilename().toLocal8Bit(),
41 << sf_strerror(m_file) << ")" << std::endl; 44 SFM_WRITE, &fileInfo);
42 m_error = QString("Failed to open audio file '%1' for writing") 45 if (!m_file) {
43 .arg(m_path); 46 std::cerr << "WavFileWriter: Failed to open file ("
47 << sf_strerror(m_file) << ")" << std::endl;
48 m_error = QString("Failed to open audio file '%1' for writing")
49 .arg(m_temp->getTemporaryFilename());
50 }
51 } catch (FileOperationFailed &f) {
52 m_error = f.what();
53 m_temp = 0;
54 m_file = 0;
44 } 55 }
45 } 56 }
46 57
47 WavFileWriter::~WavFileWriter() 58 WavFileWriter::~WavFileWriter()
48 { 59 {
63 74
64 bool 75 bool
65 WavFileWriter::writeModel(DenseTimeValueModel *source, 76 WavFileWriter::writeModel(DenseTimeValueModel *source,
66 MultiSelection *selection) 77 MultiSelection *selection)
67 { 78 {
79 if (!m_temp) {
80 m_error = QString("Failed to write model to audio file: No file open");
81 return false;
82 }
83
68 if (source->getChannelCount() != m_channels) { 84 if (source->getChannelCount() != m_channels) {
69 std::cerr << "WavFileWriter::writeModel: Wrong number of channels (" 85 std::cerr << "WavFileWriter::writeModel: Wrong number of channels ("
70 << source->getChannelCount() << " != " << m_channels << ")" 86 << source->getChannelCount() << " != " << m_channels << ")"
71 << std::endl; 87 << std::endl;
72 m_error = QString("Failed to write model to audio file '%1'") 88 m_error = QString("Failed to write model to audio file '%1'")
73 .arg(m_path); 89 .arg(m_temp->getTemporaryFilename());
74 return false; 90 return false;
75 } 91 }
76 92
77 if (!m_file) { 93 if (!m_file) {
78 m_error = QString("Failed to write model to audio file '%1': File not open") 94 m_error = QString("Failed to write model to audio file '%1': File not open")
79 .arg(m_path); 95 .arg(m_temp->getTemporaryFilename());
80 return false; 96 return false;
81 } 97 }
82 98
83 bool ownSelection = false; 99 bool ownSelection = false;
84 if (!selection) { 100 if (!selection) {
127 } 143 }
128 144
129 bool 145 bool
130 WavFileWriter::writeSamples(float **samples, size_t count) 146 WavFileWriter::writeSamples(float **samples, size_t count)
131 { 147 {
148 if (!m_temp) {
149 m_error = QString("Failed to write model to audio file: No file open");
150 return false;
151 }
152
132 if (!m_file) { 153 if (!m_file) {
133 m_error = QString("Failed to write model to audio file '%1': File not open") 154 m_error = QString("Failed to write model to audio file '%1': File not open")
134 .arg(m_path); 155 .arg(m_temp->getTemporaryFilename());
135 return false; 156 return false;
136 } 157 }
137 158
138 float *b = new float[count * m_channels]; 159 float *b = new float[count * m_channels];
139 for (size_t i = 0; i < count; ++i) { 160 for (size_t i = 0; i < count; ++i) {
159 { 180 {
160 if (m_file) { 181 if (m_file) {
161 sf_close(m_file); 182 sf_close(m_file);
162 m_file = 0; 183 m_file = 0;
163 } 184 }
185 m_temp->moveToTarget();
186 delete m_temp;
187 m_temp = 0;
164 return true; 188 return true;
165 } 189 }
166 190