1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-26 17:18:41 +02:00

Eliminate some more news and deletes, with the help of class Maybe...

... which can stack-allocate an object conditionally.

(Name inspired by Haskell.)
This commit is contained in:
Paul Licameli 2016-02-25 20:18:46 -05:00
commit 0eb4de9304
11 changed files with 268 additions and 174 deletions

View File

@ -242,4 +242,118 @@ namespace std {
}
#endif
/*
* template class Maybe<X>
* Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed.
* You might also use it as a member.
* Initialize with create(), then use like a smart pointer,
* with *, ->, get(), reset(), or in if()
*/
template<typename X>
class Maybe {
public:
// Construct as NULL
Maybe() {}
// Supply the copy and move, so you might use this as a class member too
Maybe(const Maybe &that)
{
if (that.get())
create(*that);
}
Maybe& operator= (const Maybe &that)
{
if (this != &that) {
if (that.get())
create(*that);
else
reset();
}
return *this;
}
Maybe(Maybe &&that)
{
if (that.get())
create(::std::move(*that));
}
Maybe& operator= (Maybe &&that)
{
if (this != &that) {
if (that.get())
create(::std::move(*that));
else
reset();
}
return *this;
}
// Make an object in the buffer, passing constructor arguments,
// but destroying any previous object first
// Note that if constructor throws, we remain in a consistent
// NULL state -- giving exception safety but only weakly
// (previous value was lost if present)
template<typename... Args>
void create(Args... args)
{
// Lose any old value
reset();
// Create new value
pp = safenew(address()) X( std::forward<Args>(args)... );
}
// Destroy any object that was built in it
~Maybe()
{
reset();
}
// Pointer-like operators
// Dereference, with the usual bad consequences if NULL
X &operator* () const
{
return *pp;
}
X *operator-> () const
{
return pp;
}
X* get() const
{
return pp;
}
void reset()
{
if (pp)
pp->~X(), pp = nullptr;
}
// So you can say if(ptr)
explicit operator bool() const
{
return pp != nullptr;
}
private:
X* address()
{
return reinterpret_cast<X*>(&storage);
}
// Data
typename ::std::aligned_storage<
sizeof(X)
// , alignof(X) // Not here yet in all compilers
>::type storage{};
X* pp{ nullptr };
};
#endif // __AUDACITY_H__

View File

@ -317,7 +317,7 @@ void QuitAudacity(bool bForce)
AudacityProject::DeleteAllProjectsDeleteLock();
//remove our logger
delete wxLog::SetActiveTarget(NULL);
std::unique_ptr<wxLog>{ wxLog::SetActiveTarget(NULL) }; // DELETE
if (bForce)
{
@ -1147,7 +1147,7 @@ bool AudacityApp::OnInit()
// Ensure we have an event loop during initialization
wxEventLoopGuarantor eventLoop;
delete wxLog::SetActiveTarget(new AudacityLogger);
std::unique_ptr < wxLog > { wxLog::SetActiveTarget(new AudacityLogger) }; // DELETE
mLocale = NULL;

View File

@ -1343,72 +1343,67 @@ bool AudioIO::StartPortAudioStream(double sampleRate,
mNumPlaybackChannels = numPlaybackChannels;
mNumCaptureChannels = numCaptureChannels;
PaStreamParameters *playbackParameters = NULL;
PaStreamParameters *captureParameters = NULL;
bool usePlayback = false, useCapture = false;
PaStreamParameters playbackParameters{};
PaStreamParameters captureParameters{};
double latencyDuration = DEFAULT_LATENCY_DURATION;
gPrefs->Read(wxT("/AudioIO/LatencyDuration"), &latencyDuration);
if( numPlaybackChannels > 0)
{
playbackParameters = new PaStreamParameters;
usePlayback = true;
// this sets the device index to whatever is "right" based on preferences,
// then defaults
playbackParameters->device = getPlayDevIndex();
playbackParameters.device = getPlayDevIndex();
const PaDeviceInfo *playbackDeviceInfo;
playbackDeviceInfo = Pa_GetDeviceInfo( playbackParameters->device );
playbackDeviceInfo = Pa_GetDeviceInfo( playbackParameters.device );
if( playbackDeviceInfo == NULL )
{
delete playbackParameters;
return false;
}
// regardless of source formats, we always mix to float
playbackParameters->sampleFormat = paFloat32;
playbackParameters->hostApiSpecificStreamInfo = NULL;
playbackParameters->channelCount = mNumPlaybackChannels;
playbackParameters.sampleFormat = paFloat32;
playbackParameters.hostApiSpecificStreamInfo = NULL;
playbackParameters.channelCount = mNumPlaybackChannels;
if (mSoftwarePlaythrough)
playbackParameters->suggestedLatency =
playbackParameters.suggestedLatency =
playbackDeviceInfo->defaultLowOutputLatency;
else
playbackParameters->suggestedLatency = latencyDuration/1000.0;
playbackParameters.suggestedLatency = latencyDuration/1000.0;
mOutputMeter = mOwningProject->GetPlaybackMeter();
}
if( numCaptureChannels > 0)
{
useCapture = true;
mCaptureFormat = captureFormat;
captureParameters = new PaStreamParameters;
const PaDeviceInfo *captureDeviceInfo;
// retrieve the index of the device set in the prefs, or a sensible
// default if it isn't set/valid
captureParameters->device = getRecordDevIndex();
captureParameters.device = getRecordDevIndex();
captureDeviceInfo = Pa_GetDeviceInfo( captureParameters->device );
captureDeviceInfo = Pa_GetDeviceInfo( captureParameters.device );
if( captureDeviceInfo == NULL )
{
delete captureParameters;
delete playbackParameters;
return false;
}
captureParameters->sampleFormat =
captureParameters.sampleFormat =
AudacityToPortAudioSampleFormat(mCaptureFormat);
captureParameters->hostApiSpecificStreamInfo = NULL;
captureParameters->channelCount = mNumCaptureChannels;
captureParameters.hostApiSpecificStreamInfo = NULL;
captureParameters.channelCount = mNumCaptureChannels;
if (mSoftwarePlaythrough)
captureParameters->suggestedLatency =
captureParameters.suggestedLatency =
captureDeviceInfo->defaultHighInputLatency;
else
captureParameters->suggestedLatency = latencyDuration/1000.0;
captureParameters.suggestedLatency = latencyDuration/1000.0;
mInputMeter = mOwningProject->GetCaptureMeter();
}
@ -1429,7 +1424,8 @@ bool AudioIO::StartPortAudioStream(double sampleRate,
#endif
#endif
mLastPaError = Pa_OpenStream( &mPortStreamV19,
captureParameters, playbackParameters,
useCapture ? &captureParameters : NULL,
usePlayback ? &playbackParameters : NULL,
mRate, paFramesPerBufferUnspecified,
paNoFlag,
audacityAudioCallback, NULL );
@ -1457,10 +1453,6 @@ bool AudioIO::StartPortAudioStream(double sampleRate,
}
#endif
// these may be null, but deleting a null pointer should never crash.
delete captureParameters;
delete playbackParameters;
return (mLastPaError == paNoError);
}

View File

@ -597,14 +597,16 @@ AliasBlockFile::~AliasBlockFile()
bool AliasBlockFile::ReadSummary(void *data)
{
wxFFile summaryFile(mFileName.GetFullPath(), wxT("rb"));
wxLogNull *silence=0;
if(mSilentLog)silence= new wxLogNull();
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
if (!summaryFile.IsOpened()){
// NEW model; we need to return valid data
memset(data, 0, (size_t)mSummaryInfo.totalSummaryBytes);
if(silence) delete silence;
// we silence the logging for this operation in this object
// after first occurrence of error; it's already reported and
@ -613,9 +615,9 @@ bool AliasBlockFile::ReadSummary(void *data)
mSilentLog = TRUE;
return true;
}else mSilentLog=FALSE; // worked properly, any future error is NEW
if(silence) delete silence;
}
else mSilentLog = FALSE; // worked properly, any future error is NEW
}
int read = summaryFile.Read(data, (size_t)mSummaryInfo.totalSummaryBytes);

View File

@ -197,7 +197,6 @@ static int RecursivelyEnumerate(wxString dirPath,
return count;
}
static int RecursivelyEnumerateWithProgress(wxString dirPath,
wxArrayString& filePathArray, // output: all files in dirPath tree
wxString dirspec,
@ -205,19 +204,16 @@ static int RecursivelyEnumerateWithProgress(wxString dirPath,
int progress_count,
const wxChar* message)
{
ProgressDialog *progress = NULL;
Maybe<ProgressDialog> progress{};
if (message)
progress = new ProgressDialog(_("Progress"), message);
progress.create( _("Progress"), message );
int count = RecursivelyEnumerate(
dirPath, filePathArray, dirspec,
bFiles, bDirs,
progress_count, 0,
progress);
if (progress)
delete progress;
progress.get());
return count;
}
@ -291,10 +287,10 @@ static void RecursivelyRemove(wxArrayString& filePathArray, int count,
bool bFiles, bool bDirs,
const wxChar* message = NULL)
{
ProgressDialog *progress = NULL;
Maybe<ProgressDialog> progress{};
if (message)
progress = new ProgressDialog(_("Progress"), message);
progress.create( _("Progress"), message );
for (int i = 0; i < count; i++) {
const wxChar *file = filePathArray[i].c_str();
@ -305,9 +301,6 @@ static void RecursivelyRemove(wxArrayString& filePathArray, int count,
if (progress)
progress->Update(i, count);
}
if (progress)
delete progress;
}

View File

@ -69,10 +69,12 @@ void ComputeLegacySummaryInfo(wxFileName fileName,
SampleBuffer data(info->frames64K * fields,
info->format);
wxLogNull *silence=0;
wxFFile summaryFile(fileName.GetFullPath(), wxT("rb"));
int read;
if(Silent)silence= new wxLogNull();
{
Maybe<wxLogNull> silence{};
wxFFile summaryFile(fileName.GetFullPath(), wxT("rb"));
if (Silent)
silence.create();
if (!summaryFile.IsOpened()) {
wxLogWarning(wxT("Unable to access summary file %s; substituting silence for remainder of session"),
@ -80,14 +82,14 @@ void ComputeLegacySummaryInfo(wxFileName fileName,
read = info->frames64K * info->bytesPerFrame;
memset(data.ptr(), 0, read);
}else{
}
else{
summaryFile.Seek(info->offset64K);
read = summaryFile.Read(data.ptr(),
info->frames64K *
info->bytesPerFrame);
}
if(silence) delete silence;
}
int count = read / info->bytesPerFrame;
@ -151,22 +153,23 @@ LegacyBlockFile::~LegacyBlockFile()
bool LegacyBlockFile::ReadSummary(void *data)
{
wxFFile summaryFile(mFileName.GetFullPath(), wxT("rb"));
wxLogNull *silence=0;
if(mSilentLog)silence= new wxLogNull();
int read;
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
if (!summaryFile.IsOpened()){
memset(data, 0, (size_t)mSummaryInfo.totalSummaryBytes);
if(silence) delete silence;
mSilentLog = TRUE;
return true;
}
int read = summaryFile.Read(data, (size_t)mSummaryInfo.totalSummaryBytes);
if(silence) delete silence;
read = summaryFile.Read(data, (size_t)mSummaryInfo.totalSummaryBytes);
}
mSilentLog=FALSE;
return (read == mSummaryInfo.totalSummaryBytes);
@ -215,19 +218,20 @@ int LegacyBlockFile::ReadData(samplePtr data, sampleFormat format,
sf = sf_open_fd(f.fd(), SFM_READ, &info, FALSE);
}
wxLogNull *silence=0;
if(mSilentLog)silence= new wxLogNull();
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
if (!sf){
memset(data, 0, SAMPLE_SIZE(format)*len);
if(silence) delete silence;
mSilentLog = TRUE;
return len;
}
if(silence) delete silence;
}
mSilentLog=FALSE;
sf_count_t seekstart = start +

View File

@ -80,13 +80,14 @@ int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
return len;
}
wxLogNull *silence=0;
if(mSilentAliasLog)silence= new wxLogNull();
memset(&info, 0, sizeof(info));
wxFile f; // will be closed when it goes out of scope
SNDFILE *sf = NULL;
{
Maybe<wxLogNull> silence{};
if (mSilentAliasLog)
silence.create();
memset(&info, 0, sizeof(info));
if (f.Exists(mAliasedFileName.GetFullPath())) { // Don't use Open if file does not exits
if (f.Open(mAliasedFileName.GetFullPath())) {
@ -101,7 +102,7 @@ int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
if (!sf){
memset(data, 0, SAMPLE_SIZE(format)*len);
if(silence) delete silence;
silence.reset();
mSilentAliasLog = TRUE;
// Set a marker to display an error message for the silence
@ -109,8 +110,7 @@ int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
wxGetApp().MarkAliasedFilesMissingWarning(this);
return len;
}
if(silence) delete silence;
}
mSilentAliasLog=FALSE;
ODManager::LockLibSndFileMutex();

View File

@ -345,21 +345,21 @@ bool SimpleBlockFile::ReadSummary(void *data)
wxFFile file(mFileName.GetFullPath(), wxT("rb"));
wxLogNull *silence=0;
if(mSilentLog)silence= new wxLogNull();
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
if (!file.IsOpened()){
memset(data, 0, (size_t)mSummaryInfo.totalSummaryBytes);
if(silence) delete silence;
mSilentLog = TRUE;
return true;
}
if(silence) delete silence;
}
mSilentLog=FALSE;
// The offset is just past the au header
@ -400,13 +400,14 @@ int SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
//wxLogDebug("SimpleBlockFile::ReadData(): Reading data from disk.");
SF_INFO info;
wxLogNull *silence=0;
if(mSilentLog)silence= new wxLogNull();
memset(&info, 0, sizeof(info));
wxFile f; // will be closed when it goes out of scope
SNDFILE *sf = NULL;
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
memset(&info, 0, sizeof(info));
if (f.Open(mFileName.GetFullPath())) {
// Even though there is an sf_open() that takes a filename, use the one that
@ -419,12 +420,11 @@ int SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
memset(data, 0, SAMPLE_SIZE(format)*len);
if(silence) delete silence;
mSilentLog = TRUE;
return len;
}
if(silence) delete silence;
}
mSilentLog=FALSE;
sf_seek(sf, start, SEEK_SET);

View File

@ -456,7 +456,7 @@ bool VSTEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxStrin
wxString effectIDs = wxT("0;");
wxStringTokenizer effectTzr(effectIDs, wxT(";"));
wxProgressDialog *progress = NULL;
Maybe<wxProgressDialog> progress{};
size_t idCnt = 0;
size_t idNdx = 0;
@ -517,10 +517,10 @@ bool VSTEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxStrin
idCnt = effectTzr.CountTokens();
if (idCnt > 3)
{
progress = new wxProgressDialog(_("Scanning Shell VST"),
progress.create( _("Scanning Shell VST"),
wxString::Format(_("Registering %d of %d: %-64.64s"), 0, idCnt, proc.GetName().c_str()),
idCnt,
NULL,
static_cast<int>(idCnt),
nullptr,
wxPD_APP_MODAL |
wxPD_AUTO_HIDE |
wxPD_CAN_ABORT |
@ -611,11 +611,6 @@ bool VSTEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxStrin
}
}
if (progress)
{
delete progress;
}
return valid;
}

View File

@ -213,7 +213,7 @@ int MP3ImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks,
mPrivateData.file = mFile;
mPrivateData.inputBuffer = new unsigned char [INPUT_BUFFER_SIZE];
mPrivateData.progress = mProgress;
mPrivateData.progress = mProgress.get();
mPrivateData.channels = NULL;
mPrivateData.updateResult= eProgressSuccess;
mPrivateData.id3checked = false;

View File

@ -119,17 +119,12 @@ class ImportFileHandle /* not final */
public:
ImportFileHandle(const wxString & filename)
: mFilename(filename),
mProgress(NULL)
mProgress{}
{
}
virtual ~ImportFileHandle()
{
if (mProgress != NULL)
{
delete mProgress;
mProgress = NULL;
}
}
// The importer should call this to create the progress dialog and
@ -140,8 +135,7 @@ public:
wxString title;
title.Printf(_("Importing %s"), GetFileDescription().c_str());
mProgress = new ProgressDialog(title,
f.GetFullName());
mProgress.create(title, f.GetFullName());
}
// This is similar to GetImporterDescription, but if possible the
@ -170,7 +164,7 @@ public:
protected:
wxString mFilename;
ProgressDialog *mProgress;
Maybe<ProgressDialog> mProgress;
};