mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 00:29:41 +02:00
Bug1829, more: check all errors flushing and closing export files...
... MP3 export already did this, the other five needed work.
This commit is contained in:
parent
b3b4ace739
commit
38568f611d
@ -209,10 +209,17 @@ int ufile_close(AVIOContext *pb)
|
||||
{
|
||||
std::unique_ptr<wxFile> f{ (wxFile *)pb->opaque };
|
||||
|
||||
if (f)
|
||||
f->Close();
|
||||
bool success = true;
|
||||
if (f) {
|
||||
success = f->Flush() && f->Close();
|
||||
pb->opaque = nullptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
// We're not certain that a close error is for want of space, but we'll
|
||||
// guess that
|
||||
return success ? 0 : -ENOSPC;
|
||||
|
||||
// Implicitly destroy the wxFile object here
|
||||
}
|
||||
|
||||
// Open a file with a (possibly) Unicode filename
|
||||
|
26
src/FFmpeg.h
26
src/FFmpeg.h
@ -928,6 +928,18 @@ private:
|
||||
|
||||
// Deleter adaptor for functions like av_free that take a pointer
|
||||
template<typename T, typename R, R(*Fn)(T*)> struct AV_Deleter {
|
||||
inline R operator() (T* p) const
|
||||
{
|
||||
R result{};
|
||||
if (p)
|
||||
result = Fn(p);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization of previous for void return
|
||||
template<typename T, void(*Fn)(T*)>
|
||||
struct AV_Deleter<T, void, Fn> {
|
||||
inline void operator() (T* p) const
|
||||
{
|
||||
if (p)
|
||||
@ -959,9 +971,19 @@ using AVCodecContextHolder = std::unique_ptr<
|
||||
using AVDictionaryCleanup = std::unique_ptr<
|
||||
AVDictionary*, AV_Deleter<AVDictionary*, void, av_dict_free>
|
||||
>;
|
||||
using UFileHolder = std::unique_ptr<
|
||||
struct UFileHolder : public std::unique_ptr<
|
||||
AVIOContext, AV_Deleter<AVIOContext, int, ufile_close>
|
||||
>;
|
||||
>
|
||||
{
|
||||
// Close explicitly, not ignoring return values.
|
||||
int close()
|
||||
{
|
||||
auto result = get_deleter() ( get() );
|
||||
release();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> using AVMallocHolder = std::unique_ptr<
|
||||
T, AV_Deleter<void, void, av_free>
|
||||
>;
|
||||
|
@ -288,7 +288,7 @@ OSType sf_header_mactype(int format)
|
||||
|
||||
ODLock libSndFileMutex;
|
||||
|
||||
void SFFileCloser::operator() (SNDFILE *sf) const
|
||||
int SFFileCloser::operator() (SNDFILE *sf) const
|
||||
{
|
||||
auto err = SFCall<int>(sf_close, sf);
|
||||
if (err) {
|
||||
@ -299,4 +299,5 @@ void SFFileCloser::operator() (SNDFILE *sf) const
|
||||
(_("Error (file may not have been written): %s"),
|
||||
buffer));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -127,7 +127,16 @@ inline R SFCall(F fun, Args&&... args)
|
||||
}
|
||||
|
||||
//RAII for SNDFILE*
|
||||
struct SFFileCloser { void operator () (SNDFILE*) const; };
|
||||
using SFFile = std::unique_ptr<SNDFILE, SFFileCloser>;
|
||||
struct SFFileCloser { int operator () (SNDFILE*) const; };
|
||||
struct SFFile : public std::unique_ptr<SNDFILE, SFFileCloser>
|
||||
{
|
||||
// Close explicitly, not ignoring return values.
|
||||
int close()
|
||||
{
|
||||
auto result = get_deleter() ( get() );
|
||||
release();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -52,11 +52,18 @@ bool FileIO::IsOpened()
|
||||
return mOpen;
|
||||
}
|
||||
|
||||
void FileIO::Close()
|
||||
bool FileIO::Close()
|
||||
{
|
||||
mOutputStream.reset();
|
||||
bool success = true;
|
||||
if (mOutputStream) {
|
||||
// mOutputStream->Sync() returns void! Rrr!
|
||||
success = mOutputStream->GetFile()->Flush() &&
|
||||
mOutputStream->Close();
|
||||
mOutputStream.reset();
|
||||
}
|
||||
mInputStream.reset();
|
||||
mOpen = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
wxInputStream & FileIO::Read(void *buf, size_t size)
|
||||
|
@ -32,7 +32,7 @@ class FileIO
|
||||
|
||||
bool IsOpened();
|
||||
|
||||
void Close();
|
||||
bool Close();
|
||||
|
||||
wxInputStream & Read(void *buffer, size_t size);
|
||||
wxOutputStream & Write(const void *buffer, size_t size);
|
||||
@ -41,7 +41,7 @@ class FileIO
|
||||
wxString mName;
|
||||
FileIOMode mMode;
|
||||
std::unique_ptr<wxInputStream> mInputStream;
|
||||
std::unique_ptr<wxOutputStream> mOutputStream;
|
||||
std::unique_ptr<wxFFileOutputStream> mOutputStream;
|
||||
bool mOpen;
|
||||
};
|
||||
|
||||
|
@ -945,6 +945,12 @@ ProgressResult ExportFFmpeg::Export(AudacityProject *project,
|
||||
if ( !Finalize() ) // Finalize makes its own messages
|
||||
return ProgressResult::Cancelled;
|
||||
|
||||
if ( mUfileCloser.close() != 0 ) {
|
||||
// TODO: more precise message
|
||||
AudacityMessageBox(_("Unable to export"));
|
||||
return ProgressResult::Cancelled;
|
||||
}
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
|
@ -335,10 +335,13 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
||||
mMetadata.reset();
|
||||
|
||||
auto cleanup2 = finally( [&] {
|
||||
if (!(updateResult == ProgressResult::Success ||
|
||||
updateResult == ProgressResult::Stopped)) {
|
||||
#ifndef LEGACY_FLAC
|
||||
f.Detach(); // libflac closes the file
|
||||
f.Detach(); // libflac closes the file
|
||||
#endif
|
||||
encoder.finish();
|
||||
encoder.finish();
|
||||
}
|
||||
} );
|
||||
|
||||
const WaveTrackConstArray waveTracks =
|
||||
@ -389,6 +392,20 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
||||
}
|
||||
}
|
||||
|
||||
if (updateResult == ProgressResult::Success ||
|
||||
updateResult == ProgressResult::Stopped) {
|
||||
#ifndef LEGACY_FLAC
|
||||
f.Detach(); // libflac closes the file
|
||||
#endif
|
||||
if (!encoder.finish())
|
||||
// Do not reassign updateResult, see cleanup2
|
||||
return ProgressResult::Failed;
|
||||
#ifdef LEGACY_FLAC
|
||||
if (!f.Flush() || !f.Close())
|
||||
return ProgressResult::Failed;
|
||||
#endif
|
||||
}
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,11 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
|
||||
return ProgressResult::Cancelled;
|
||||
}
|
||||
|
||||
outFile.Close();
|
||||
if ( !outFile.Close() ) {
|
||||
// TODO: more precise message
|
||||
AudacityMessageBox(_("Unable to export"));
|
||||
return ProgressResult::Cancelled;
|
||||
}
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
@ -359,7 +359,11 @@ ProgressResult ExportOGG::Export(AudacityProject *project,
|
||||
}
|
||||
}
|
||||
|
||||
outFile.Close();
|
||||
if ( !outFile.Close() ) {
|
||||
updateResult = ProgressResult::Cancelled;
|
||||
// TODO: more precise message
|
||||
AudacityMessageBox(_("Unable to export"));
|
||||
}
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
@ -530,7 +530,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
|
||||
|
||||
// Install the WAV metata in a "LIST" chunk at the end of the file
|
||||
if (updateResult == ProgressResult::Success ||
|
||||
updateResult == ProgressResult::Stopped)
|
||||
updateResult == ProgressResult::Stopped) {
|
||||
if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV ||
|
||||
(sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAVEX) {
|
||||
if (!AddStrings(project, sf.get(), metadata, sf_format)) {
|
||||
@ -538,6 +538,12 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
|
||||
AudacityMessageBox(_("Unable to export"));
|
||||
return ProgressResult::Cancelled;
|
||||
}
|
||||
}
|
||||
if (0 != sf.close()) {
|
||||
// TODO: more precise message
|
||||
AudacityMessageBox(_("Unable to export"));
|
||||
return ProgressResult::Cancelled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,6 +551,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
|
||||
updateResult == ProgressResult::Stopped)
|
||||
if (((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF) ||
|
||||
((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV))
|
||||
// Note: file has closed, and gets reopened and closed again here:
|
||||
if (!AddID3Chunk(fName, metadata, sf_format) ) {
|
||||
// TODO: more precise message
|
||||
AudacityMessageBox(_("Unable to export"));
|
||||
@ -845,6 +852,9 @@ bool ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
|
||||
if (4 != f.Write(&sz, 4))
|
||||
return false;
|
||||
|
||||
if (!f.Flush())
|
||||
return false;
|
||||
|
||||
if (!f.Close())
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user