1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-30 23:23:44 +02:00

Define classes and functions for exception handling framework

This commit is contained in:
Paul Licameli 2017-03-16 11:57:20 -04:00
commit 40e73cdcdd
14 changed files with 653 additions and 0 deletions

View File

@ -1205,16 +1205,21 @@
28FE4A080ABF4E960056F5C4 /* mmx_optimized.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FE4A060ABF4E960056F5C4 /* mmx_optimized.cpp */; };
28FE4A090ABF4E960056F5C4 /* sse_optimized.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FE4A070ABF4E960056F5C4 /* sse_optimized.cpp */; };
5E02BFF21D1164DF00EB7578 /* Distortion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E02BFF01D1164DF00EB7578 /* Distortion.cpp */; };
5E07842E1DEE6B8600CA76EA /* FileException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E07842C1DEE6B8600CA76EA /* FileException.cpp */; };
5E0784311DF1E4F400CA76EA /* UserException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E07842F1DF1E4F400CA76EA /* UserException.cpp */; };
5E0A0E311D23019A00CD2567 /* MenusMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E0A0E301D23019A00CD2567 /* MenusMac.cpp */; };
5E74D2E31CC4429700D88B0B /* EditCursorOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */; };
5E74D2E41CC4429700D88B0B /* PlayIndicatorOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */; };
5E74D2E51CC4429700D88B0B /* Scrubbing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */; };
5E78388E1DE4995F003270C0 /* AudacityException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E78388D1DE4995E003270C0 /* AudacityException.cpp */; };
5E79B3411D5CC38D001D677D /* ImportGStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E79B33F1D5CC38D001D677D /* ImportGStreamer.cpp */; };
5E94A1BA1D1F1C8400A8713A /* wxPanelWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E94A1B81D1F1C8400A8713A /* wxPanelWrapper.cpp */; };
5EC7ED061E101C5C0052CAE2 /* NotYetAvailableException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EC7ED041E101C5C0052CAE2 /* NotYetAvailableException.cpp */; };
5ED1D0AD1CDE55BD00471E3C /* Overlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0A91CDE55BD00471E3C /* Overlay.cpp */; };
5ED1D0AE1CDE55BD00471E3C /* OverlayPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0AB1CDE55BD00471E3C /* OverlayPanel.cpp */; };
5ED1D0B11CDE560C00471E3C /* BackedPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0AF1CDE560C00471E3C /* BackedPanel.cpp */; };
5EF17C231D1F0A690090A642 /* ScrubbingToolBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF17C211D1F0A690090A642 /* ScrubbingToolBar.cpp */; };
5EF958851DEB121800191280 /* InconsistencyException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF958831DEB121800191280 /* InconsistencyException.cpp */; };
8406A93812D0F2510011EA01 /* EQDefaultCurves.xml in Resources */ = {isa = PBXBuildFile; fileRef = 8406A93712D0F2510011EA01 /* EQDefaultCurves.xml */; };
8484F31413086237002DF7F0 /* DeviceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8484F31213086237002DF7F0 /* DeviceManager.cpp */; };
ED15214D163C22F000451B5F /* lsr.c in Sources */ = {isa = PBXBuildFile; fileRef = ED152123163C220300451B5F /* lsr.c */; };
@ -2977,6 +2982,10 @@
28FEC1B21A12B6FB00FACE48 /* EffectAutomationParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EffectAutomationParameters.h; path = ../include/audacity/EffectAutomationParameters.h; sourceTree = SOURCE_ROOT; };
5E02BFF01D1164DF00EB7578 /* Distortion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Distortion.cpp; sourceTree = "<group>"; };
5E02BFF11D1164DF00EB7578 /* Distortion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Distortion.h; sourceTree = "<group>"; };
5E07842C1DEE6B8600CA76EA /* FileException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileException.cpp; sourceTree = "<group>"; };
5E07842D1DEE6B8600CA76EA /* FileException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileException.h; sourceTree = "<group>"; };
5E07842F1DF1E4F400CA76EA /* UserException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserException.cpp; sourceTree = "<group>"; };
5E0784301DF1E4F400CA76EA /* UserException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserException.h; sourceTree = "<group>"; };
5E0A0E301D23019A00CD2567 /* MenusMac.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = MenusMac.cpp; sourceTree = "<group>"; };
5E4685F81CCA9D84008741F2 /* CommandFunctors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommandFunctors.h; sourceTree = "<group>"; };
5E61EE0C1CBAA6BB0009FCF1 /* MemoryX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryX.h; sourceTree = "<group>"; };
@ -2988,12 +2997,16 @@
5E74D2E01CC4429700D88B0B /* PlayIndicatorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayIndicatorOverlay.h; sourceTree = "<group>"; };
5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scrubbing.cpp; sourceTree = "<group>"; };
5E74D2E21CC4429700D88B0B /* Scrubbing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scrubbing.h; sourceTree = "<group>"; };
5E78388D1DE4995E003270C0 /* AudacityException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudacityException.cpp; sourceTree = "<group>"; };
5E7838931DE4BBC2003270C0 /* CommandFlag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommandFlag.h; sourceTree = "<group>"; };
5E79B33F1D5CC38D001D677D /* ImportGStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImportGStreamer.cpp; sourceTree = "<group>"; };
5E79B3401D5CC38D001D677D /* ImportGStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImportGStreamer.h; sourceTree = "<group>"; };
5E94A1B81D1F1C8400A8713A /* wxPanelWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wxPanelWrapper.cpp; sourceTree = "<group>"; };
5E94A1B91D1F1C8400A8713A /* wxPanelWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wxPanelWrapper.h; sourceTree = "<group>"; };
5EB9EA281D5B81270050AF40 /* ImportForwards.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImportForwards.h; sourceTree = "<group>"; };
5EC7ED041E101C5C0052CAE2 /* NotYetAvailableException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NotYetAvailableException.cpp; sourceTree = "<group>"; };
5EC7ED051E101C5C0052CAE2 /* NotYetAvailableException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotYetAvailableException.h; sourceTree = "<group>"; };
5ECCE7651DE49834009900E9 /* AudacityException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudacityException.h; sourceTree = "<group>"; };
5ED18DB61CC16B1E00FAFE95 /* Reverb_libSoX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reverb_libSoX.h; sourceTree = "<group>"; };
5ED18DB71CC290AB00FAFE95 /* wxFileNameWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wxFileNameWrapper.h; sourceTree = "<group>"; };
5ED1D0A91CDE55BD00471E3C /* Overlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Overlay.cpp; sourceTree = "<group>"; };
@ -3004,6 +3017,8 @@
5ED1D0B01CDE560C00471E3C /* BackedPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackedPanel.h; sourceTree = "<group>"; };
5EF17C211D1F0A690090A642 /* ScrubbingToolBar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrubbingToolBar.cpp; sourceTree = "<group>"; };
5EF17C221D1F0A690090A642 /* ScrubbingToolBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrubbingToolBar.h; sourceTree = "<group>"; };
5EF958831DEB121800191280 /* InconsistencyException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InconsistencyException.cpp; sourceTree = "<group>"; };
5EF958841DEB121800191280 /* InconsistencyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InconsistencyException.h; sourceTree = "<group>"; };
82FF184D13CF01A600C1B664 /* dBTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dBTable.cpp; path = sbsms/src/dBTable.cpp; sourceTree = "<group>"; };
82FF184E13CF01A600C1B664 /* dBTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dBTable.h; path = sbsms/src/dBTable.h; sourceTree = "<group>"; };
82FF184F13CF01A600C1B664 /* slide.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = slide.cpp; path = sbsms/src/slide.cpp; sourceTree = "<group>"; };
@ -3833,6 +3848,7 @@
1790AFC709883BFD008A330A /* AboutDialog.cpp */,
1790AFC909883BFD008A330A /* AColor.cpp */,
1790AFCE09883BFD008A330A /* AudacityApp.cpp */,
5E78388D1DE4995E003270C0 /* AudacityException.cpp */,
28C3946B1818356800FDDAC9 /* AudacityLogger.cpp */,
1790AFD209883BFD008A330A /* AudioIO.cpp */,
28560C8F0A75E40F00A3429E /* AutoRecovery.cpp */,
@ -3851,6 +3867,7 @@
1790B05F09883BFD008A330A /* Envelope.cpp */,
283135FD0DFBA2E80076D551 /* FFmpeg.cpp */,
1790B07009883BFD008A330A /* FFT.cpp */,
5E07842C1DEE6B8600CA76EA /* FileException.cpp */,
1790B07209883BFD008A330A /* FileFormats.cpp */,
2809C4B60BCB7E560006010F /* FileIO.cpp */,
28F00A900A3E2FF100A3E5F5 /* FileNames.cpp */,
@ -3858,6 +3875,7 @@
28501E9D0CEECEF80029ABAA /* HelpText.cpp */,
1790B07909883BFD008A330A /* HistoryWindow.cpp */,
1790B07B09883BFD008A330A /* ImageManipulation.cpp */,
5EF958831DEB121800191280 /* InconsistencyException.cpp */,
1790B09909883BFD008A330A /* Internat.cpp */,
28EBA7FD0A78FAF800C8BB1F /* InterpolateAudio.cpp */,
280828530A75E0D0000002EF /* LabelDialog.cpp */,
@ -3907,6 +3925,7 @@
1790B0EC09883BFD008A330A /* TrackPanel.cpp */,
1790B0EE09883BFD008A330A /* TrackPanelAx.cpp */,
1790B0F209883BFD008A330A /* UndoManager.cpp */,
5E07842F1DF1E4F400CA76EA /* UserException.cpp */,
28C8211C1B5C661E00B53328 /* ViewInfo.cpp */,
1790B0F709883BFD008A330A /* VoiceKey.cpp */,
1790B0F909883BFD008A330A /* WaveClip.cpp */,
@ -3917,6 +3936,7 @@
28FB12230A3790DF006F0917 /* AllThemeResources.h */,
1790AFCC09883BFD008A330A /* Audacity.h */,
1790AFCF09883BFD008A330A /* AudacityApp.h */,
5ECCE7651DE49834009900E9 /* AudacityException.h */,
1790AFD009883BFD008A330A /* AudacityHeaders.h */,
28C3946C1818356800FDDAC9 /* AudacityLogger.h */,
1790AFD309883BFD008A330A /* AudioIO.h */,
@ -3939,6 +3959,7 @@
1790B06109883BFD008A330A /* Experimental.h */,
283135FE0DFBA2E80076D551 /* FFmpeg.h */,
1790B07109883BFD008A330A /* FFT.h */,
5E07842D1DEE6B8600CA76EA /* FileException.h */,
1790B07309883BFD008A330A /* FileFormats.h */,
2809C4B70BCB7E560006010F /* FileIO.h */,
28F00A910A3E2FF100A3E5F5 /* FileNames.h */,
@ -3947,6 +3968,7 @@
28501E9E0CEECEF80029ABAA /* HelpText.h */,
1790B07A09883BFD008A330A /* HistoryWindow.h */,
1790B07C09883BFD008A330A /* ImageManipulation.h */,
5EF958841DEB121800191280 /* InconsistencyException.h */,
1790B09A09883BFD008A330A /* Internat.h */,
28EBA7FE0A78FAF800C8BB1F /* InterpolateAudio.h */,
280828540A75E0D0000002EF /* LabelDialog.h */,
@ -4004,6 +4026,7 @@
2803C8B619F35AA000278526 /* TrackPanelListener.h */,
284416391B82D6BC0000574D /* TranslatableStringArray.h */,
1790B0F309883BFD008A330A /* UndoManager.h */,
5E0784301DF1E4F400CA76EA /* UserException.h */,
1790B0F609883BFD008A330A /* ViewInfo.h */,
1790B0F809883BFD008A330A /* VoiceKey.h */,
1790B0FA09883BFD008A330A /* WaveClip.h */,
@ -4034,6 +4057,8 @@
1790AFDF09883BFD008A330A /* LegacyAliasBlockFile.h */,
1790AFE009883BFD008A330A /* LegacyBlockFile.cpp */,
1790AFE109883BFD008A330A /* LegacyBlockFile.h */,
5EC7ED041E101C5C0052CAE2 /* NotYetAvailableException.cpp */,
5EC7ED051E101C5C0052CAE2 /* NotYetAvailableException.h */,
186CCE6B0E51F47400659159 /* ODDecodeBlockFile.cpp */,
186CCE6C0E51F47400659159 /* ODDecodeBlockFile.h */,
1841B50F0E00AD8D00F386E9 /* ODPCMAliasBlockFile.cpp */,
@ -7353,6 +7378,7 @@
1790B13F09883BFD008A330A /* LadspaEffect.cpp in Sources */,
1790B14109883BFD008A330A /* Leveller.cpp in Sources */,
1790B14209883BFD008A330A /* LoadEffects.cpp in Sources */,
5E0784311DF1E4F400CA76EA /* UserException.cpp in Sources */,
1790B14309883BFD008A330A /* Noise.cpp in Sources */,
1790B14409883BFD008A330A /* NoiseRemoval.cpp in Sources */,
1790B14509883BFD008A330A /* Normalize.cpp in Sources */,
@ -7381,6 +7407,7 @@
1790B16109883BFD008A330A /* FFT.cpp in Sources */,
1790B16209883BFD008A330A /* FileFormats.cpp in Sources */,
1790B16309883BFD008A330A /* FreqWindow.cpp in Sources */,
5EC7ED061E101C5C0052CAE2 /* NotYetAvailableException.cpp in Sources */,
1790B16509883BFD008A330A /* HistoryWindow.cpp in Sources */,
1790B16609883BFD008A330A /* ImageManipulation.cpp in Sources */,
5E79B3411D5CC38D001D677D /* ImportGStreamer.cpp in Sources */,
@ -7490,6 +7517,7 @@
2891B2870C531D2C0044FBE3 /* FindClipping.cpp in Sources */,
283AA0EB0C56ED08002CBD34 /* ErrorDialog.cpp in Sources */,
28501EA10CEECEF80029ABAA /* HelpText.cpp in Sources */,
5EF958851DEB121800191280 /* InconsistencyException.cpp in Sources */,
28501EA20CEECEF80029ABAA /* SplashDialog.cpp in Sources */,
28501EAA0CEED0670029ABAA /* LoadVamp.cpp in Sources */,
5ED1D0AD1CDE55BD00471E3C /* Overlay.cpp in Sources */,
@ -7508,6 +7536,7 @@
1841B50E0E00AD6E00F386E9 /* ODWaveTrackTaskQueue.cpp in Sources */,
1841B5110E00AD8D00F386E9 /* ODPCMAliasBlockFile.cpp in Sources */,
2860BA240E0F0D8600A13878 /* SoundActivatedRecord.cpp in Sources */,
5E07842E1DEE6B8600CA76EA /* FileException.cpp in Sources */,
2860BA250E0F0D8600A13878 /* TimerRecordDialog.cpp in Sources */,
2860BA280E0F0DD800A13878 /* ExportFFmpeg.cpp in Sources */,
28D587CB0E264CF4009C7DEA /* LoadLV2.cpp in Sources */,
@ -7529,6 +7558,7 @@
284B279C0FC66864005EAC96 /* LibraryPrefs.cpp in Sources */,
284B279D0FC66864005EAC96 /* PlaybackPrefs.cpp in Sources */,
284B279E0FC66864005EAC96 /* ProjectsPrefs.cpp in Sources */,
5E78388E1DE4995F003270C0 /* AudacityException.cpp in Sources */,
284B279F0FC66864005EAC96 /* RecordingPrefs.cpp in Sources */,
284B27E40FC66CCD005EAC96 /* TracksPrefs.cpp in Sources */,
284B27E50FC66CCD005EAC96 /* WarningsPrefs.cpp in Sources */,

69
src/AudacityException.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "Audacity.h"
#include "AudacityException.h"
#include <wx/atomic.h>
#include <wx/msgdlg.h>
AudacityException::~AudacityException()
{
}
wxAtomicInt sOutstandingMessages {};
MessageBoxException::MessageBoxException( const wxString &caption_ )
: caption{ caption_ }
{
wxAtomicInc( sOutstandingMessages );
}
// The class needs a copy constructor to be throwable
// (or will need it, by C++14 rules). But the copy
// needs to act like a move constructor. There must be unique responsibility
// for each exception thrown to decrease the global count when it is handled.
MessageBoxException::MessageBoxException( const MessageBoxException& that )
{
caption = that.caption;
moved = that.moved;
that.moved = true;
}
MessageBoxException &MessageBoxException::operator = ( MessageBoxException &&that )
{
caption = that.caption;
if ( this != &that ) {
if (!moved)
wxAtomicDec( sOutstandingMessages );
moved = that.moved;
that.moved = true;
}
return *this;
}
MessageBoxException::~MessageBoxException()
{
if (!moved)
// If exceptions are used properly, you should never reach this,
// because moved should become true earlier in the object's lifetime.
wxAtomicDec( sOutstandingMessages );
}
// This is meant to be invoked via wxEvtHandler::CallAfter
void MessageBoxException::DelayedHandlerAction()
{
if (!moved) {
// This test prevents accumulation of multiple messages between idle
// times of the main even loop. Only the last queued exception
// displays its message. We assume that multiple messages have a
// common cause such as exhaustion of disk space so that the others
// give the user no useful added information.
if ( wxAtomicDec( sOutstandingMessages ) == 0 )
::wxMessageBox(
ErrorMessage(),
caption.IsEmpty() ? wxMessageBoxCaptionStr : caption,
wxICON_ERROR
);
moved = true;
}
}

181
src/AudacityException.h Normal file
View File

@ -0,0 +1,181 @@
#ifndef __AUDACITY_EXCEPTION__
#define __AUDACITY_EXCEPTION__
/**********************************************************************
Audacity: A Digital Audio Editor
AudacityException.h
Paul Licameli
Define the root of a hierarchy of classes that are thrown and caught
by Audacity.
Define some subclasses. Not all subclasses need be defined here.
**********************************************************************/
#include "MemoryX.h"
#include <wx/app.h>
class wxString;
class AudacityException /* not final */
{
public:
AudacityException() {}
virtual ~AudacityException() = 0;
// This is intended as a "polymorphic move copy constructor"
// which leaves this "empty".
// We would not need this if we had std::exception_ptr
virtual std::unique_ptr< AudacityException > Move() = 0;
// Action to do in the main thread at idle time of the event loop.
virtual void DelayedHandlerAction() = 0;
protected:
// Make this protected to prevent slicing copies
AudacityException( AudacityException&& ) {}
AudacityException( const AudacityException& ) = default;
AudacityException &operator = (AudacityException &&) {}
AudacityException &operator = ( const AudacityException & ) PROHIBITED;
};
// A subclass of AudacityException whose delayed handler action displays
// a message box. The message is specified by further subclasses.
// Not more than one message box will be displayed for each pass through
// the main event idle loop.
class MessageBoxException /* not final */ : public AudacityException
{
// Do not allow subclasses to change this behavior further, except
// by overriding ErrorMessage()
using AudacityException::DelayedHandlerAction;
void DelayedHandlerAction() override;
protected:
explicit MessageBoxException( const wxString &caption = wxString{} );
~MessageBoxException() override;
MessageBoxException( const MessageBoxException& );
MessageBoxException &operator = ( MessageBoxException && );
// Format a default, internationalized error message for this exception.
virtual wxString ErrorMessage() const = 0;
private:
wxString caption;
mutable bool moved { false };
};
struct DefaultDelayedHandlerAction
{
void operator () (AudacityException *pException) const
{
if ( pException )
pException->DelayedHandlerAction();
}
};
// Helpers for defining GuardedCall:
// Call one function object,
// then another unless the first throws, return result of first
template <typename R> struct Sequencer {
template <typename F1, typename Argument, typename F2>
R operator () (const F1 &f1, Argument &&a, const F2 &f2)
{
auto result = f1( std::forward<Argument>(a) );
f2();
return result;
}
};
// template specialization to allow R to be void
template <> struct Sequencer<void> {
template <typename F1, typename Argument, typename F2>
void operator () (const F1 &f1, Argument &&a, const F2 &f2)
{
f1( std::forward<Argument>(a) );
f2();
}
};
// Classes that can supply the second argument of GuardedCall:
// Frequently useful converter of all exceptions to some failure constant
template <typename R> struct SimpleGuard
{
explicit SimpleGuard( R value ) : m_value{ value } {}
R operator () ( AudacityException * ) const { return m_value; }
const R m_value;
};
// Simple guard specialization that returns bool, and defines Default
template<> struct SimpleGuard<bool>
{
explicit SimpleGuard( bool value ) : m_value{ value } {}
bool operator () ( AudacityException * ) const { return m_value; }
static SimpleGuard Default()
{ return SimpleGuard{ false }; }
const bool m_value;
};
// Simple guard specialization that returns nothing, and defines Default
template<> struct SimpleGuard<void>
{
SimpleGuard() {}
void operator () ( AudacityException * ) const {}
static SimpleGuard Default() { return {}; }
};
template < typename R >
SimpleGuard< R > MakeSimpleGuard( R value )
{ return SimpleGuard< R >{ value }; }
inline SimpleGuard< void > MakeSimpleGuard() { return {}; }
/**
* Call the body function (usually a lambda) inside a try block.
*
* The handler intercepts exceptions, and is passed nullptr if the
* exception is of a type not defined by Audacity. It may return a value
* for the guarded call or throw the same or another exception.
* It executes in the same thread as the body.
*
* If the handler catches non-null and does not throw, then delayedHandler
* executes later in the main thread, in idle time of the event loop.
*/
template <
typename R, // return type
typename F1, // function object with signature R()
typename F2 = SimpleGuard< R >, // function object
// with signature R( AudacityException * )
typename F3 =
DefaultDelayedHandlerAction // Any( AudacityException * ), ignore return
>
R GuardedCall
( const F1 &body,
const F2 &handler = F2::Default(),
const F3 &delayedHandler = {} )
{
try { return body(); }
catch ( AudacityException &e ) {
return Sequencer<R>{}( handler, &e,
[&] {
auto pException =
std::shared_ptr< AudacityException > { e.Move().release() };
wxTheApp->CallAfter( [=] { // capture pException by value
delayedHandler( pException.get() );
} );
}
);
}
catch ( ... ) {
return handler( nullptr );
}
}
#endif

45
src/FileException.cpp Normal file
View File

@ -0,0 +1,45 @@
//
// FileException.cpp
//
//
// Created by Paul Licameli on 11/22/16.
//
//
#include "Audacity.h"
#include "FileException.h"
FileException::~FileException()
{
}
std::unique_ptr< AudacityException > FileException::Move()
{
return std::unique_ptr< AudacityException >
{ safenew FileException{ std::move( *this ) } };
}
wxString FileException::ErrorMessage() const
{
wxString format;
switch (cause) {
case Cause::Open:
format = _("Audacity failed to open a file at %s.\n");
break;
case Cause::Read:
format = _("Audacity failed to read from a file at %s.\n");
break;
case Cause::Write:
format = _(
"Audacity failed to write to a file at %s.\nAttempt this operation again after removing unnecessary files.\nOne way to do that is with the Discard buttons in the History dialog.\nSee the View menu.");
break;
case Cause::Rename:
format = _(
"Audacity successfully wrote the file %s but failed to rename it as %s.");
default:
break;
}
return wxString::Format(
format, fileName.GetFullPath(), renameTarget.GetFullPath() );
}

46
src/FileException.h Normal file
View File

@ -0,0 +1,46 @@
//
// FileException.h
//
//
// Created by Paul Licameli on 11/22/16.
//
//
#ifndef __AUDACITY_FILE_EXCEPTION__
#define __AUDACITY_FILE_EXCEPTION__
#include "AudacityException.h"
#include <wx/filename.h>
class FileException /* not final */ : public MessageBoxException
{
public:
enum class Cause { Open, Read, Write, Rename };
explicit FileException
( Cause cause_, const wxFileName &fileName_,
const wxString &caption = wxString{},
const wxFileName &renameTarget_ = {})
: MessageBoxException{ caption }
, fileName{ fileName_ }, cause{ cause_ }, renameTarget{ renameTarget_ }
{}
FileException(FileException&& that)
: MessageBoxException(std::move(that))
{}
~FileException() override;
protected:
std::unique_ptr< AudacityException > Move() override;
// Format a default, internationalized error message for this exception.
wxString ErrorMessage() const override;
public:
Cause cause;
wxFileName fileName;
wxFileName renameTarget;
};
#endif

View File

@ -0,0 +1,42 @@
//
// InconsistencyException.cpp
//
//
// Created by Paul Licameli on 11/27/16.
//
//
#include "Audacity.h"
#include "InconsistencyException.h"
InconsistencyException::~InconsistencyException()
{
}
std::unique_ptr< AudacityException > InconsistencyException::Move()
{
return std::unique_ptr< AudacityException >
{ safenew InconsistencyException{ std::move( *this ) } };
}
wxString InconsistencyException::ErrorMessage() const
{
// Shorten the path
wxString path { file };
auto sub = wxString{ wxFILE_SEP_PATH } + "src" + wxFILE_SEP_PATH;
auto index = path.Find(sub);
if (index != wxNOT_FOUND)
path = path.Mid(index + sub.size());
#ifdef __func__
return wxString::Format(
_("Internal error in %s at %s line %d.\nPlease inform the Audacity team at feedback@audacityteam.org."),
func, path, line
);
#else
return wxString::Format(
_("Internal error at %s line %d.\nPlease inform the Audacity team at feedback@audacityteam.org."),
path, line
);
#endif
}

View File

@ -0,0 +1,68 @@
//
// InconsistencyException.h
//
//
// Created by Paul Licameli on 11/27/16.
//
// Some errors that formerly were assertion violations now throw exceptions,
// even in production code. These may be violations of function preconditions
// or the results of logical errors internal to functions. These conditions
// are supposed to be deducible statically as never happening.
//
#ifndef __AUDACITY_INCONSISTENCY_EXCEPTION__
#define __AUDACITY_INCONSISTENCY_EXCEPTION__
#include "AudacityException.h"
class InconsistencyException final : public MessageBoxException
{
public:
InconsistencyException() {}
explicit InconsistencyException
( const char *fn, const char *f, unsigned l )
: func { fn }, file { f }, line { l }
{}
InconsistencyException(InconsistencyException&& that)
: MessageBoxException(std::move(that))
{}
InconsistencyException &operator = (InconsistencyException &&that)
{
if (this != &that)
operator= (std::move(that));
return *this;
}
~InconsistencyException() override;
private:
std::unique_ptr< AudacityException > Move() override;
// Format a default, internationalized error message for this exception.
wxString ErrorMessage() const override;
const char *func {};
const char *file {};
unsigned line {};
};
// This macro constructs this exception type, using C++ preprocessor to identify
// the source code location.
#ifdef __func__
#define CONSTRUCT_INCONSISTENCY_EXCEPTION \
InconsistencyException( __func__, __FILE__ , __LINE__ )
#else
#define CONSTRUCT_INCONSISTENCY_EXCEPTION \
InconsistencyException( "", __FILE__ , __LINE__ )
#endif
#define THROW_INCONSISTENCY_EXCEPTION throw CONSTRUCT_INCONSISTENCY_EXCEPTION
#endif

View File

@ -32,6 +32,8 @@ libaudacity_la_SOURCES = \
blockfile/LegacyAliasBlockFile.h \
blockfile/LegacyBlockFile.cpp \
blockfile/LegacyBlockFile.h \
blockfile/NotYetAvailableException.cpp \
blockfile/NotYetAvailableException.h \
blockfile/ODDecodeBlockFile.cpp \
blockfile/ODDecodeBlockFile.h \
blockfile/ODPCMAliasBlockFile.cpp \
@ -101,6 +103,8 @@ audacity_SOURCES = \
Audacity.h \
AudacityApp.cpp \
AudacityApp.h \
AudacityException.cpp \
AudacityException.h \
AudacityLogger.cpp \
AudacityLogger.h \
AudioIO.cpp \
@ -131,6 +135,8 @@ audacity_SOURCES = \
FFmpeg.h \
FFT.cpp \
FFT.h \
FileException.cpp \
FileException.h \
FileIO.cpp \
FileIO.h \
FileNames.cpp \
@ -144,6 +150,8 @@ audacity_SOURCES = \
HistoryWindow.h \
ImageManipulation.cpp \
ImageManipulation.h \
InconsistencyException.cpp \
InconsistencyException.h \
InterpolateAudio.cpp \
InterpolateAudio.h \
LabelDialog.cpp \
@ -239,6 +247,8 @@ audacity_SOURCES = \
TranslatableStringArray.h \
UndoManager.cpp \
UndoManager.h \
UserException.cpp \
UserException.h \
ViewInfo.cpp \
ViewInfo.h \
VoiceKey.cpp \

24
src/UserException.cpp Normal file
View File

@ -0,0 +1,24 @@
//
// UserException.cpp
//
//
// Created by Paul Licameli on 11/27/16.
//
//
#include "Audacity.h"
#include "UserException.h"
UserException::~UserException()
{
}
std::unique_ptr< AudacityException > UserException::Move()
{
return std::unique_ptr< AudacityException >
{ safenew UserException{ std::move( *this ) } };
}
void UserException::DelayedHandlerAction()
{
}

36
src/UserException.h Normal file
View File

@ -0,0 +1,36 @@
//
// UserException.h
//
//
// Created by Paul Licameli on 11/27/16.
//
// An exception to throw when the user cancels an operation, as for instance
// with a progress dialog. Its delayed handler action does nothing.
//
#ifndef __AUDACITY_USER_EXCEPTION__
#define __AUDACITY_USER_EXCEPTION__
#include "AudacityException.h"
// This class does not inherit from MessageBoxException, and it does nothing
// in its delayed handler. It might be thrown after the user clicks a
// cancel button, as on a progress dialog.
class UserException final : public AudacityException
{
public:
UserException() {}
UserException(UserException &&that)
: AudacityException{ std::move( that ) }
{}
~UserException() override;
void DelayedHandlerAction() override;
private:
std::unique_ptr< AudacityException > Move() override;
};
#endif

View File

@ -0,0 +1,28 @@
//
// NotYetAvailableException.cpp
//
//
// Created by Paul Licameli on 12/25/16.
//
//
#include "../Audacity.h"
#include "NotYetAvailableException.h"
NotYetAvailableException::~NotYetAvailableException()
{
}
std::unique_ptr< AudacityException > NotYetAvailableException::Move()
{
return std::unique_ptr< AudacityException >
{ safenew NotYetAvailableException{ std::move( *this ) } };
}
wxString NotYetAvailableException::ErrorMessage() const
{
return wxString::Format(
_("This operation cannot be done until importation of %s completes."),
mFileName.GetFullName()
);
}

View File

@ -0,0 +1,34 @@
//
// NotYetAvailableException.h
//
//
// Created by Paul Licameli on 12/25/16.
//
//
#ifndef __AUDACITY_NOT_YET_AVAILABLE_EXCEPTION__
#define __AUDACITY_NOT_YET_AVAILABLE_EXCEPTION__
#include "../FileException.h"
#include <wx/filename.h>
// This exception can be thrown when attempting read of on-demand block files
// that have not yet completed loading.
class NotYetAvailableException final : public FileException
{
public:
NotYetAvailableException( const wxFileName &fileName )
: FileException{ Cause::Read, fileName } {}
NotYetAvailableException(NotYetAvailableException &&that)
: FileException( std::move( that ) ) {}
~NotYetAvailableException();
protected:
std::unique_ptr< AudacityException > Move() override;
wxString ErrorMessage() const override;
private:
wxFileName mFileName;
};
#endif

View File

@ -121,6 +121,7 @@
<ClCompile Include="..\..\..\src\AboutDialog.cpp" />
<ClCompile Include="..\..\..\src\AColor.cpp" />
<ClCompile Include="..\..\..\src\AudacityApp.cpp" />
<ClCompile Include="..\..\..\src\AudacityException.cpp" />
<ClCompile Include="..\..\..\src\AudacityHeaders.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
@ -133,6 +134,7 @@
<ClCompile Include="..\..\..\src\BatchProcessDialog.cpp" />
<ClCompile Include="..\..\..\src\Benchmark.cpp" />
<ClCompile Include="..\..\..\src\BlockFile.cpp" />
<ClCompile Include="..\..\..\src\blockfile\NotYetAvailableException.cpp" />
<ClCompile Include="..\..\..\src\commands\OpenSaveCommands.cpp" />
<ClCompile Include="..\..\..\src\Dependencies.cpp" />
<ClCompile Include="..\..\..\src\DeviceChange.cpp" />
@ -149,6 +151,7 @@
<ClCompile Include="..\..\..\src\Envelope.cpp" />
<ClCompile Include="..\..\..\src\FFmpeg.cpp" />
<ClCompile Include="..\..\..\src\FFT.cpp" />
<ClCompile Include="..\..\..\src\FileException.cpp" />
<ClCompile Include="..\..\..\src\FileFormats.cpp" />
<ClCompile Include="..\..\..\src\FileIO.cpp" />
<ClCompile Include="..\..\..\src\FileNames.cpp" />
@ -160,6 +163,7 @@
<ClCompile Include="..\..\..\src\import\ImportGStreamer.cpp" />
<ClCompile Include="..\..\..\src\import\MultiFormatReader.cpp" />
<ClCompile Include="..\..\..\src\import\SpecPowerMeter.cpp" />
<ClCompile Include="..\..\..\src\InconsistencyException.cpp" />
<ClCompile Include="..\..\..\src\Internat.cpp" />
<ClCompile Include="..\..\..\src\InterpolateAudio.cpp" />
<ClCompile Include="..\..\..\src\LabelDialog.cpp" />
@ -222,6 +226,7 @@
<ClCompile Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.cpp" />
<ClCompile Include="..\..\..\src\tracks\ui\Scrubbing.cpp" />
<ClCompile Include="..\..\..\src\UndoManager.cpp" />
<ClCompile Include="..\..\..\src\UserException.cpp" />
<ClCompile Include="..\..\..\src\ViewInfo.cpp" />
<ClCompile Include="..\..\..\src\VoiceKey.cpp" />
<ClCompile Include="..\..\..\src\WaveClip.cpp" />
@ -411,6 +416,7 @@
<ClInclude Include="..\..\..\src\AllThemeResources.h" />
<ClInclude Include="..\..\..\src\Audacity.h" />
<ClInclude Include="..\..\..\src\AudacityApp.h" />
<ClInclude Include="..\..\..\src\AudacityException.h" />
<ClInclude Include="..\..\..\src\AudacityHeaders.h" />
<ClInclude Include="..\..\..\src\AudacityLogger.h" />
<ClInclude Include="..\..\..\src\AudioIO.h" />
@ -421,6 +427,7 @@
<ClInclude Include="..\..\..\src\BatchProcessDialog.h" />
<ClInclude Include="..\..\..\src\Benchmark.h" />
<ClInclude Include="..\..\..\src\BlockFile.h" />
<ClInclude Include="..\..\..\src\blockfile\NotYetAvailableException.h" />
<ClInclude Include="..\..\..\src\commands\CommandFlag.h" />
<ClInclude Include="..\..\..\src\commands\CommandFunctors.h" />
<ClInclude Include="..\..\..\src\commands\OpenSaveCommands.h" />
@ -432,11 +439,13 @@
<ClInclude Include="..\..\..\src\effects\NoiseReduction.h" />
<ClInclude Include="..\..\..\src\effects\Phaser.h" />
<ClInclude Include="..\..\..\src\effects\VST\VSTControlMSW.h" />
<ClInclude Include="..\..\..\src\FileException.h" />
<ClInclude Include="..\..\..\src\import\FormatClassifier.h" />
<ClInclude Include="..\..\..\src\import\ImportForwards.h" />
<ClInclude Include="..\..\..\src\import\ImportGStreamer.h" />
<ClInclude Include="..\..\..\src\import\MultiFormatReader.h" />
<ClInclude Include="..\..\..\src\import\SpecPowerMeter.h" />
<ClInclude Include="..\..\..\src\InconsistencyException.h" />
<ClInclude Include="..\..\..\src\MemoryX.h" />
<ClInclude Include="..\..\..\src\ModuleManager.h" />
<ClInclude Include="..\..\..\src\NumberScale.h" />
@ -458,6 +467,7 @@
<ClInclude Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.h" />
<ClInclude Include="..\..\..\src\tracks\ui\Scrubbing.h" />
<ClInclude Include="..\..\..\src\TranslatableStringArray.h" />
<ClInclude Include="..\..\..\src\UserException.h" />
<ClInclude Include="..\..\..\src\WaveTrackLocation.h" />
<ClInclude Include="..\..\..\src\widgets\BackedPanel.h" />
<ClInclude Include="..\..\..\src\widgets\HelpSystem.h" />

View File

@ -887,6 +887,21 @@
<ClCompile Include="..\..\..\src\widgets\wxPanelWrapper.cpp">
<Filter>src\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\AudacityException.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\InconsistencyException.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\FileException.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\UserException.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\blockfile\NotYetAvailableException.cpp">
<Filter>src\blockfile</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\AboutDialog.h">
@ -1801,6 +1816,21 @@
<ClInclude Include="..\..\..\src\commands\CommandFlag.h">
<Filter>src\commands</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\AudacityException.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\InconsistencyException.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\FileException.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\UserException.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\blockfile\NotYetAvailableException.h">
<Filter>src\blockfile</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\..\audacity.ico">