diff --git a/src/AboutDialog.cpp b/src/AboutDialog.cpp
index b84da0b6e..d7f46ccc7 100644
--- a/src/AboutDialog.cpp
+++ b/src/AboutDialog.cpp
@@ -120,6 +120,7 @@ void AboutDialog::CreateCreditsList()
    AddCredit(wxString(wxT("Jun Wan, ")) + _("developer"), roleContributor);
    AddCredit(wxString(wxT("Daniel Winzen, ")) + _("developer"), roleContributor);
    AddCredit(wxString(wxT("Tom Woodhams, ")) + _("developer"), roleContributor);
+   AddCredit(wxString(wxT("Mark Young, ")) + _("developer"), roleContributor);
    AddCredit(wxString(wxT("Wing Yu, ")) + _("developer"), roleContributor);
 
    // Translators
diff --git a/src/Menus.cpp b/src/Menus.cpp
index e60fe4d7d..ebae67322 100644
--- a/src/Menus.cpp
+++ b/src/Menus.cpp
@@ -144,6 +144,18 @@ enum {
    kAlignTogether
 };
 
+// Post Timer Recording Actions
+// Ensure this matches the enum in TimerRecordDialog.cpp
+enum {
+   POST_TIMER_RECORD_STOPPED = -3,
+   POST_TIMER_RECORD_CANCEL_WAIT,
+   POST_TIMER_RECORD_CANCEL,
+   POST_TIMER_RECORD_NOTHING,
+   POST_TIMER_RECORD_CLOSE,
+   POST_TIMER_RECORD_RESTART,
+   POST_TIMER_RECORD_SHUTDOWN
+};
+
 // Define functor subclasses that dispatch to the correct call sequence on
 // member functions of AudacityProject
 
@@ -6308,24 +6320,79 @@ void AudacityProject::OnNewTimeTrack()
 
 void AudacityProject::OnTimerRecord()
 {
+   // MY: Due to improvements in how Timer Recording saves and/or exports
+   // it is now safer to disable Timer Recording when there is more than
+   // one open project.
+   if (GetOpenProjectCount() > 1) {
+      wxMessageBox(_("Timer Recording cannot be used with more than one open project.\n\n\
+                     Please close any additional projects and try again."),
+                   _("Timer Recording"),
+                   wxICON_INFORMATION | wxOK);
+      return;
+   }
+
+   // MY: If the project has unsaved changes then we no longer allow access
+   // to Timer Recording.  This decision has been taken as the safest approach
+   // preventing issues surrounding "dirty" projects when Automatic Save/Export
+   // is used in Timer Recording.
+   if ((GetUndoManager()->UnsavedChanges()) && (ProjectHasTracks() || mEmptyCanBeDirty)) {
+      wxMessageBox(_("Timer Recording cannot be used while you have unsaved changes.\n\nPlease save or close this project and try again."),
+                   _("Timer Recording"),
+                   wxICON_INFORMATION | wxOK);
+      return;
+   }
+   // We use this variable to display "Current Project" in the Timer Recording save project field
+   bool bProjectSaved = IsProjectSaved();
+
    //we break the prompting and waiting dialogs into two sections
    //because they both give the user a chance to click cancel
    //and therefore remove the newly inserted track.
 
-   TimerRecordDialog dialog(this /* parent */ );
+   TimerRecordDialog dialog(this, bProjectSaved); /* parent, project saved? */
    int modalResult = dialog.ShowModal();
    if (modalResult == wxID_CANCEL)
    {
       // Cancelled before recording - don't need to do anyting.
    }
-   else if(!dialog.RunWaitDialog())
+   else
    {
-      //RunWaitDialog() shows the "wait for start" as well as "recording" dialog
-      //if it returned false it means the user cancelled while the recording, so throw out the fresh track.
-      //However, we can't undo it here because the PushState() is called in TrackPanel::OnTimer(),
-      //which is blocked by this function.
-      //so instead we mark a flag to undo it there.
-      mTimerRecordCanceled = true;
+      int iTimerRecordingOutcome = dialog.RunWaitDialog();
+      switch (iTimerRecordingOutcome) {
+      case POST_TIMER_RECORD_CANCEL_WAIT:
+         // Canceled on the wait dialog
+         if (GetUndoManager()->UndoAvailable()) {
+            // MY: We need to roll back what changes we have made here
+            OnUndo();
+         }
+      break;
+      case POST_TIMER_RECORD_CANCEL:
+         // RunWaitDialog() shows the "wait for start" as well as "recording" dialog
+         // if it returned POST_TIMER_RECORD_CANCEL it means the user cancelled while the recording, so throw out the fresh track.
+         // However, we can't undo it here because the PushState() is called in TrackPanel::OnTimer(),
+         // which is blocked by this function.
+         // so instead we mark a flag to undo it there.
+         mTimerRecordCanceled = true;
+      break;
+      case POST_TIMER_RECORD_NOTHING:
+         // No action required
+      break;
+      case POST_TIMER_RECORD_CLOSE:
+         // Quit Audacity
+         exit(0);
+      break;
+      case POST_TIMER_RECORD_RESTART:
+         // Restart System
+#ifdef __WINDOWS__
+         system("shutdown /r /f /t 30");
+#endif
+      break;
+      case POST_TIMER_RECORD_SHUTDOWN:
+         // Shutdown System
+#ifdef __WINDOWS__
+         system("shutdown /s /f /t 30");
+#endif
+      break;
+      }
    }
 }
 
diff --git a/src/Project.cpp b/src/Project.cpp
index c30b24f91..4d4daf3fb 100644
--- a/src/Project.cpp
+++ b/src/Project.cpp
@@ -2168,10 +2168,8 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
       gAudioIO->StopStream();
    }
 
-   // These two lines test for an 'empty' project.
-   // of course it could still have a history at this stage.
-   TrackListIterator iter2(mTracks);
-   bool bHasTracks = (iter2.First() != NULL);
+   // MY: Use routine here so other processes can make same check
+   bool bHasTracks = ProjectHasTracks();
 
    // We may not bother to prompt the user to save, if the
    // project is now empty.
@@ -5193,3 +5191,66 @@ void AudacityProject::ReleaseKeyboard(wxWindow * /* handler */)
 
    return;
 }
+
+bool AudacityProject::ExportFromTimerRecording(wxFileName fnFile, int iFormat, int iSubFormat, int iFilterIndex)
+{
+   Exporter e;
+
+   wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
+   return e.ProcessFromTimerRecording(this, false, 0.0, mTracks->GetEndTime(), fnFile, iFormat, iSubFormat, iFilterIndex);
+}
+
+int AudacityProject::GetOpenProjectCount() {
+   return gAudacityProjects.Count();
+}
+
+bool AudacityProject::IsProjectSaved() {
+   wxString sProjectName = mDirManager->GetProjectName();
+   return (sProjectName != wxT(""));
+}
+
+bool AudacityProject::SaveFromTimerRecording(wxFileName fnFile) {
+   // MY: Will save the project to a new location a-la Save As
+   // and then tidy up after itself.
+
+   wxString sNewFileName = fnFile.GetFullPath();
+
+   // MY: To allow SaveAs from Timer Recording we need to check what
+   // the value of mFileName is befoer we change it.
+   wxString sOldFilename = "";
+   if (IsProjectSaved()) {
+      sOldFilename = mFileName;
+   }
+
+   // MY: If the project file already exists then bail out
+   // and send populate the message string (pointer) so
+   // we can tell the user what went wrong.
+   if (wxFileExists(sNewFileName)) {
+      return false;
+   }
+
+   mFileName = sNewFileName;
+   SetProjectTitle();
+
+   bool bSuccess = Save(false, true, false);
+
+   if (bSuccess) {
+      wxGetApp().AddFileToHistory(mFileName);
+   } else
+   {
+      // Reset file name on error
+      mFileName = sOldFilename;
+      SetProjectTitle();
+   }
+
+   return bSuccess;
+}
+
+// MY: Does the project have any tracks?
+bool AudacityProject::ProjectHasTracks() {
+   // These two lines test for an 'empty' project.
+   // of course it could still have a history at this stage.
+   TrackListIterator iter2(mTracks);
+   bool bHasTracks = (iter2.First() != NULL);
+   return bHasTracks;
+}
diff --git a/src/Project.h b/src/Project.h
index a27a09cc8..4ec80706e 100644
--- a/src/Project.h
+++ b/src/Project.h
@@ -275,6 +275,14 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
      */
    wxDialog *GetMissingAliasFileDialog();
 
+   // Timer Record Auto Save/Export Routines
+   bool SaveFromTimerRecording(wxFileName fnFile);
+   bool ExportFromTimerRecording(wxFileName fnFile, int iFormat, int iSubFormat, int iFilterIndex);
+   int GetOpenProjectCount();
+   bool IsProjectSaved();
+
+   bool ProjectHasTracks();
+
 #include "Menus.h"
 
    CommandManager *GetCommandManager() { return &mCommandManager; }
diff --git a/src/ShuttleGui.cpp b/src/ShuttleGui.cpp
index aaf12d59a..8cde5e2d3 100644
--- a/src/ShuttleGui.cpp
+++ b/src/ShuttleGui.cpp
@@ -487,7 +487,6 @@ wxSpinCtrl * ShuttleGuiBase::AddSpinCtrl(const wxString &Prompt, int Value, int
    return pSpinCtrl;
 }
 
-
 wxTextCtrl * ShuttleGuiBase::AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
 {
    UseUpId();
diff --git a/src/ShuttleGui.h b/src/ShuttleGui.h
index cb6f240a3..f8ef12b67 100644
--- a/src/ShuttleGui.h
+++ b/src/ShuttleGui.h
@@ -70,7 +70,6 @@ class Shuttle;
 
 class WrappedType;
 
-
 class AUDACITY_DLL_API ShuttleGuiBase /* not final */
 {
 public:
diff --git a/src/TimerRecordDialog.cpp b/src/TimerRecordDialog.cpp
index 96790744f..758b0c823 100644
--- a/src/TimerRecordDialog.cpp
+++ b/src/TimerRecordDialog.cpp
@@ -20,6 +20,7 @@
 
 #include "Audacity.h"
 #include "TimerRecordDialog.h"
+#include "FileNames.h"
 
 #include <wx/defs.h>
 #include <wx/datetime.h>
@@ -44,7 +45,30 @@ enum { // control IDs
    ID_TIMETEXT_START,
    ID_DATEPICKER_END,
    ID_TIMETEXT_END,
-   ID_TIMETEXT_DURATION
+   ID_TIMETEXT_DURATION,
+   ID_AUTOSAVEPATH_BUTTON,
+   ID_AUTOSAVEPATH_TEXT,
+   ID_AUTOEXPORTPATH_BUTTON,
+   ID_AUTOEXPORTPATH_TEXT,
+   ID_AUTOSAVE_CHECKBOX,
+   ID_AUTOEXPORT_CHECKBOX
+};
+
+enum {
+   CONTROL_GROUP_SAVE,
+   CONTROL_GROUP_EXPORT
+};
+
+// Post Timer Recording Actions
+// Ensure this matches the enum in Menus.cpp
+enum {
+   POST_TIMER_RECORD_STOPPED = -3,
+   POST_TIMER_RECORD_CANCEL_WAIT,
+   POST_TIMER_RECORD_CANCEL,
+   POST_TIMER_RECORD_NOTHING,
+   POST_TIMER_RECORD_CLOSE,
+   POST_TIMER_RECORD_RESTART,
+   POST_TIMER_RECORD_SHUTDOWN
 };
 
 const int kTimerInterval = 50; // ms
@@ -66,9 +90,16 @@ BEGIN_EVENT_TABLE(TimerRecordDialog, wxDialog)
    EVT_BUTTON(wxID_OK, TimerRecordDialog::OnOK)
 
    EVT_TIMER(TIMER_ID, TimerRecordDialog::OnTimer)
+
+   EVT_BUTTON(ID_AUTOSAVEPATH_BUTTON, TimerRecordDialog::OnAutoSavePathButton_Click)
+   EVT_BUTTON(ID_AUTOEXPORTPATH_BUTTON, TimerRecordDialog::OnAutoExportPathButton_Click)
+
+   EVT_CHECKBOX(ID_AUTOSAVE_CHECKBOX, TimerRecordDialog::OnAutoSaveCheckBox_Change)
+   EVT_CHECKBOX(ID_AUTOEXPORT_CHECKBOX, TimerRecordDialog::OnAutoExportCheckBox_Change)
+
 END_EVENT_TABLE()
 
-TimerRecordDialog::TimerRecordDialog(wxWindow* parent)
+TimerRecordDialog::TimerRecordDialog(wxWindow* parent, bool bAlreadySaved)
 : wxDialog(parent, -1, _("Audacity Timer Record"), wxDefaultPosition,
            wxDefaultSize, wxCAPTION)
 {
@@ -88,6 +119,9 @@ TimerRecordDialog::TimerRecordDialog(wxWindow* parent)
 
    m_pTimeTextCtrl_Duration = NULL;
 
+   // Do we allow the user to change the Automatic Save file?
+   m_bProjectAlreadySaved = bAlreadySaved;
+
    ShuttleGui S(this, eIsCreating);
    this->PopulateOrExchange(S);
 
@@ -98,6 +132,10 @@ TimerRecordDialog::TimerRecordDialog(wxWindow* parent)
 
    m_timer.SetOwner(this, TIMER_ID);
    m_timer.Start(kTimerInterval);
+
+   // Do we need to tidy up when the timer recording has been completed?
+   m_bProjectCleanupRequired = !(this->HaveFilesToRecover());
+
 }
 
 TimerRecordDialog::~TimerRecordDialog()
@@ -210,6 +248,65 @@ void TimerRecordDialog::OnTimeText_Duration(wxCommandEvent& WXUNUSED(event))
    this->UpdateEnd(); // Keep Start constant and update End for changed Duration.
 }
 
+// New events for timer recording automation
+void TimerRecordDialog::OnAutoSavePathButton_Click(wxCommandEvent& WXUNUSED(event))
+{
+   wxString fName = FileSelector(_T("Save Timer Recording As"),
+      m_fnAutoSaveFile.GetPath(),
+      m_fnAutoSaveFile.GetFullName(),
+      wxT("aup"),
+      _("Audacity projects") + wxT(" (*.aup)|*.aup"),
+      wxFD_SAVE | wxRESIZE_BORDER,
+      this);
+
+   if (fName == wxT(""))
+      return;
+
+   // MY: If project already exits then abort - we do not allow users to overwrite an existing project
+   if (wxFileExists(fName)) {
+      wxMessageDialog m(
+         NULL,
+         _("The selected file name could not be used\nfor Timer Recording because it would overwrite another project.\nPlease try again and select an original name."),
+         _("Error Saving Timer Recording Project"),
+         wxOK|wxICON_ERROR);
+      m.ShowModal();
+      return;
+   }
+
+   // MY: Set this boolean to false so we now do a SaveAs at the end of the recording
+   m_bProjectAlreadySaved = false;
+
+   m_fnAutoSaveFile = fName;
+   m_fnAutoSaveFile.SetExt(wxT("aup"));
+   this->UpdateTextBoxControls();
+}
+
+void TimerRecordDialog::OnAutoExportPathButton_Click(wxCommandEvent& WXUNUSED(event))
+{
+   AudacityProject* pProject = GetActiveProject();
+   Exporter eExporter;
+
+   // Call the Exporter to set the options required
+   if (eExporter.SetAutoExportOptions(pProject)) {
+      // Populate the options so that we can destroy this instance of the Exporter
+      m_fnAutoExportFile = eExporter.GetAutoExportFileName();
+      m_iAutoExportFormat = eExporter.GetAutoExportFormat();
+      m_iAutoExportSubFormat = eExporter.GetAutoExportSubFormat();
+      m_iAutoExportFilterIndex = eExporter.GetAutoExportFilterIndex();
+
+      // Update the text controls
+      this->UpdateTextBoxControls();
+   }
+}
+
+void TimerRecordDialog::OnAutoSaveCheckBox_Change(wxCommandEvent& WXUNUSED(event)) {
+   EnableDisableAutoControls(m_pTimerAutoSaveCheckBoxCtrl->GetValue(), CONTROL_GROUP_SAVE);
+}
+
+void TimerRecordDialog::OnAutoExportCheckBox_Change(wxCommandEvent& WXUNUSED(event)) {
+   EnableDisableAutoControls(m_pTimerAutoExportCheckBoxCtrl->GetValue(), CONTROL_GROUP_EXPORT);
+}
+
 void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event))
 {
    this->TransferDataFromWindow();
@@ -220,6 +317,23 @@ void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event))
       return;
    }
 
+   // Validate that we have a Save and/or Export path setup if the appropriate check box is ticked
+   wxString sTemp = m_fnAutoSaveFile.GetFullPath();
+   if (m_pTimerAutoSaveCheckBoxCtrl->IsChecked()) {
+      if (!m_fnAutoSaveFile.IsOk() || m_fnAutoSaveFile.IsDir()) {
+         wxMessageBox(_("Automatic Save path is invalid."),
+            _("Error in Automatic Save"), wxICON_EXCLAMATION | wxOK);
+         return;
+      }
+   }
+   if (m_pTimerAutoExportCheckBoxCtrl->IsChecked()) {
+      if (!m_fnAutoExportFile.IsOk() || m_fnAutoExportFile.IsDir()) {
+         wxMessageBox(_("Automatic Export path is invalid."),
+            _("Error in Automatic Export"), wxICON_EXCLAMATION | wxOK);
+         return;
+      }
+   }
+
    m_timer.Stop(); // Don't need to keep updating m_DateTime_Start to prevent backdating.
    this->EndModal(wxID_OK);
    wxLongLong duration = m_TimeSpan_Duration.GetSeconds();
@@ -228,24 +342,88 @@ void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event))
    gPrefs->Flush();
 }
 
-///Runs the wait for start dialog.  Returns false if the user clicks stop while we are recording
-///so that the high
-// <ANSWER-ME: so that the "high" what does what?>
-bool TimerRecordDialog::RunWaitDialog()
+void TimerRecordDialog::EnableDisableAutoControls(bool bEnable, int iControlGoup) {
+
+   if (iControlGoup == CONTROL_GROUP_EXPORT) {
+       m_pTimerExportPathTextCtrl->Enable( bEnable );
+       m_pTimerExportPathButtonCtrl->Enable( bEnable);
+   } else if (iControlGoup == CONTROL_GROUP_SAVE) {
+       m_pTimerSavePathTextCtrl->Enable( bEnable);
+       m_pTimerSavePathButtonCtrl->Enable(bEnable );
+   }
+
+   // Enable or disable the Choice box - if there is no Save or Export then this will be disabled
+   if (m_pTimerAutoSaveCheckBoxCtrl->GetValue() || m_pTimerAutoExportCheckBoxCtrl->GetValue()) {
+      m_pTimerAfterCompleteChoiceCtrl->Enable();
+   } else {
+      m_pTimerAfterCompleteChoiceCtrl->SetSelection(POST_TIMER_RECORD_NOTHING);
+      m_pTimerAfterCompleteChoiceCtrl->Disable();
+   }
+}
+
+void TimerRecordDialog::UpdateTextBoxControls() {
+   // Will update the text box controls
+   m_pTimerSavePathTextCtrl->SetValue(m_fnAutoSaveFile.GetFullPath());
+   m_pTimerExportPathTextCtrl->SetValue(m_fnAutoExportFile.GetFullPath());
+
+   // MY: Ensure we still display "Current Project" if this has already been saved
+   if (m_bProjectAlreadySaved) {
+      m_pTimerSavePathTextCtrl->SetValue(_("Current Project"));
+   }
+}
+
+// Copied from AutoRecovery.cpp - for use with Timer Recording Improvements
+bool TimerRecordDialog::HaveFilesToRecover()
+{
+   wxDir dir(FileNames::AutoSaveDir());
+   if (!dir.IsOpened()) {
+      wxMessageBox(_("Could not enumerate files in auto save directory."),
+         _("Error"), wxICON_STOP);
+      return false;
+   }
+
+   wxString filename;
+   bool c = dir.GetFirst(&filename, wxT("*.autosave"), wxDIR_FILES);
+
+   return c;
+}
+
+bool TimerRecordDialog::RemoveAllAutoSaveFiles()
+{
+   wxArrayString files;
+   wxDir::GetAllFiles(FileNames::AutoSaveDir(), &files,
+      wxT("*.autosave"), wxDIR_FILES);
+
+   for (unsigned int i = 0; i < files.GetCount(); i++)
+   {
+      if (!wxRemoveFile(files[i]))
+      {
+         // I don't think this error message is actually useful.
+         // -dmazzoni
+         //wxMessageBox(wxT("Could not remove auto save file: " + files[i]),
+         //             _("Error"), wxICON_STOP);
+         return false;
+      }
+   }
+
+   return true;
+}
+
+/// Runs the wait for start dialog.  Returns -1 if the user clicks stop while we are recording
+/// or if the post recording actions fail.
+int TimerRecordDialog::RunWaitDialog()
 {
    AudacityProject* pProject = GetActiveProject();
+   
    int updateResult = eProgressSuccess;
 
    if (m_DateTime_Start > wxDateTime::UNow())
       updateResult = this->WaitForStart();
 
-   if (updateResult != eProgressSuccess)
-   {
+   if (updateResult != eProgressSuccess)  {
       // Don't proceed, but don't treat it as canceled recording. User just canceled waiting.
-      return true;
-   }
-   else
-   {
+      return POST_TIMER_RECORD_CANCEL_WAIT;
+   } else {
       // Record for specified time.
       pProject->OnRecord();
       bool bIsRecording = true;
@@ -268,10 +446,9 @@ bool TimerRecordDialog::RunWaitDialog()
       this->OnTimer(dummyTimerEvent);
 
       // Loop for progress display during recording.
-      while (bIsRecording && (updateResult == eProgressSuccess))
-      {
-         wxMilliSleep(kTimerInterval);
+      while (bIsRecording && (updateResult == eProgressSuccess)) {
          updateResult = progress.Update();
+         wxMilliSleep(kTimerInterval);
          bIsRecording = (wxDateTime::UNow() <= m_DateTime_End); // Call UNow() again for extra accuracy...
       }
    }
@@ -282,14 +459,131 @@ bool TimerRecordDialog::RunWaitDialog()
 
    // Let the caller handle cancellation or failure from recording progress.
    if (updateResult == eProgressCancelled || updateResult == eProgressFailed)
-      return false;
+      return POST_TIMER_RECORD_CANCEL;
 
-   // Success, so let's automatically save it, for safety's sake. 
-   // If user hadn't saved it before, they'll see the Save As dialog.
-   // If user had saved it before, it will safely be saved, automatically. 
-   pProject->Save();
+   return ExecutePostRecordActions((updateResult == eProgressStopped));
+}
 
-   return true;
+int TimerRecordDialog::ExecutePostRecordActions(bool bWasStopped) {
+   // MY: We no longer automatically (and silently) call ->Save() when the 
+   // timer recording is completed.  We can now Save and/or Export depending 
+   // on the options selected by the user.
+   // Once completed, we can also close Audacity, restart the system or
+   // shutdown the system.
+   // If there was any error with the auto save or export then we will not do
+   // the actions requested and instead present an error mesasge to the user.
+   // Finally, if there is no post-record action selected then we output
+   // a dialog detailing what has been carried out instead.
+
+   AudacityProject* pProject = GetActiveProject();
+
+   bool bSaveOK = false;
+   bool bExportOK = false;
+   int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
+   int iOverriddenAction = iPostRecordAction;
+   bool bErrorOverride = false;
+
+   // Do Automatic Save?
+   if (m_bAutoSaveEnabled) {
+
+      // MY: If this project has already been saved then simply execute a Save here
+      if (m_bProjectAlreadySaved) {
+         bSaveOK = pProject->Save();
+      } else {
+         bSaveOK = pProject->SaveFromTimerRecording(m_fnAutoSaveFile);
+      }
+   }
+
+   // Do Automatic Export?
+   if (m_bAutoExportEnabled) {
+      bExportOK = pProject->ExportFromTimerRecording(m_fnAutoExportFile, m_iAutoExportFormat,
+                                                     m_iAutoExportSubFormat, m_iAutoExportFilterIndex);
+   }
+
+   // Check if we need to override the post recording action
+   bErrorOverride = ((m_bAutoSaveEnabled && !bSaveOK) || (m_bAutoExportEnabled && !bExportOK));
+   if (bErrorOverride || bWasStopped) {
+      iPostRecordAction = POST_TIMER_RECORD_NOTHING;
+   }
+
+   if (iPostRecordAction == POST_TIMER_RECORD_NOTHING) {
+      // If there is no post-record action then we can show a message indicating what has been done
+
+      wxString sMessage = (bWasStopped ? _("Timer Recording Stopped.") :
+                                         _("Timer Recording Completed."));
+
+      if (m_bAutoSaveEnabled) {
+         if (bSaveOK) {
+            sMessage.Printf("%s\n\nRecording saved: %s",
+                            sMessage, m_fnAutoSaveFile.GetFullPath());
+         } else {
+            sMessage.Printf("%s\n\nError saving recording.", sMessage);
+         }
+      }
+      if (m_bAutoExportEnabled) {
+         if (bExportOK) {
+            sMessage.Printf("%s\n\nRecording exported: %s",
+                            sMessage, m_fnAutoExportFile.GetFullPath());
+         } else {
+            sMessage.Printf("%s\n\nError exporting recording.", sMessage);
+         }
+      }
+
+      if (bErrorOverride) {
+
+         if ((iOverriddenAction != iPostRecordAction) &&
+             (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
+            // Inform the user that we have overridden the selected action
+            sMessage.Printf("%s\n\n'%s' has been canceled due to the error(s) noted above.",
+                            sMessage,
+                            m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
+         }
+
+         // Show Error Message Box
+         wxMessageBox(sMessage, _("Error"), wxICON_EXCLAMATION | wxOK);
+      } else {
+
+         if (bWasStopped && (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
+            sMessage.Printf("%s\n\n'%s' has been cancelled as the recording was stopped.",
+                            sMessage,
+                            m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
+         }
+
+         wxMessageBox(sMessage, _("Timer Recording"), wxICON_INFORMATION | wxOK);
+      }
+   }
+
+   // MY: Lets do some actions that only apply to Exit/Restart/Shutdown
+   if (iPostRecordAction >= POST_TIMER_RECORD_CLOSE) {
+      do {
+         // Lets show a warning dialog telling the user what is about to happen.
+         // If the user no longer wants to carry out this action then they can click
+         // Cancel and we will do POST_TIMER_RECORD_NOTHING instead.
+         int iDelayOutcome = PreActionDelay(iPostRecordAction, (m_bAutoSaveEnabled && bSaveOK),
+                                            (m_bAutoExportEnabled && bExportOK));
+         if (iDelayOutcome != eProgressSuccess) {
+            // Cancel the action!
+            iPostRecordAction = POST_TIMER_RECORD_NOTHING;
+            // Set this to true to avoid any chance of the temp files being deleted
+            bErrorOverride = true;
+            break;
+         }
+
+         // If we have simply recorded, exported and then plan to Exit/Restart/Shutdown
+         // then we will have a temporary project setup.  Let's get rid of that!
+         if (m_bAutoExportEnabled && !m_bAutoSaveEnabled) {
+            DirManager::CleanTempDir();
+         }
+      } while (false);
+   }
+
+   // Do we need to cleanup the orphaned temporary project?
+   if (m_bProjectCleanupRequired && !bErrorOverride) {
+      RemoveAllAutoSaveFiles();
+   }
+
+   // Return the action as required
+   return iPostRecordAction;
 }
 
 wxString TimerRecordDialog::GetDisplayDate( wxDateTime & dt )
@@ -341,84 +635,166 @@ wxPrintf(wxT("%s\n"), dt.Format().c_str());
    return dt.FormatDate() + wxT(" ") + dt.FormatTime();
 }
 
+TimerRecordPathCtrl * TimerRecordDialog::NewPathControl(wxWindow *wParent, const int iID,
+                                                        const wxString &sCaption, const wxString &sValue)
+{
+   TimerRecordPathCtrl * pTextCtrl;
+   pTextCtrl = safenew TimerRecordPathCtrl(wParent, iID, sValue);
+   pTextCtrl->SetName(sCaption);
+   return pTextCtrl;
+}
+
 void TimerRecordDialog::PopulateOrExchange(ShuttleGui& S)
 {
+   bool bAutoSave = gPrefs->ReadBool("/TimerRecord/AutoSave", false);
+   bool bAutoExport = gPrefs->ReadBool("/TimerRecord/AutoExport", false);
+   int iPostTimerRecordAction = gPrefs->ReadLong("/TimerRecord/PostAction", 0);
+
    S.SetBorder(5);
-   S.StartVerticalLay(true);
+   S.StartMultiColumn(2, wxCENTER);
    {
-      /* i18n-hint: This string is used to configure the controls for times when the recording is
-       * started and stopped. As such it is important that only the alphabetic parts of the string
-       * are translated, with the numbers left exactly as they are.
-       * The 'h' indicates the first number displayed is hours, the 'm' indicates the second number
-       * displayed is minutes, and the 's' indicates that the third number displayed is seconds.
-       */
-      wxString strFormat = _("099 h 060 m 060 s");
-      S.StartStatic(_("Start Date and Time"), true);
+      S.StartVerticalLay(true);
       {
-         m_pDatePickerCtrl_Start =
-            safenew wxDatePickerCtrl(this, // wxWindow *parent,
-                                 ID_DATEPICKER_START, // wxWindowID id,
-                                 m_DateTime_Start); // const wxDateTime& dt = wxDefaultDateTime,
-                                 // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
-         m_pDatePickerCtrl_Start->SetName(_("Start Date"));
-         m_pDatePickerCtrl_Start->SetRange(wxDateTime::Today(), wxInvalidDateTime); // No backdating.
-         S.AddWindow(m_pDatePickerCtrl_Start);
+         /* i18n-hint: This string is used to configure the controls for times when the recording is
+         * started and stopped. As such it is important that only the alphabetic parts of the string
+         * are translated, with the numbers left exactly as they are.
+         * The 'h' indicates the first number displayed is hours, the 'm' indicates the second number
+         * displayed is minutes, and the 's' indicates that the third number displayed is seconds.
+         */
+         wxString strFormat = _("099 h 060 m 060 s");
+         S.StartStatic(_("Start Date and Time"), true);
+         {
+            m_pDatePickerCtrl_Start =
+               new wxDatePickerCtrl(this, // wxWindow *parent,
+               ID_DATEPICKER_START, // wxWindowID id,
+               m_DateTime_Start); // const wxDateTime& dt = wxDefaultDateTime,
+            // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
+            m_pDatePickerCtrl_Start->SetName(_("Start Date"));
+            m_pDatePickerCtrl_Start->SetRange(wxDateTime::Today(), wxInvalidDateTime); // No backdating.
+            S.AddWindow(m_pDatePickerCtrl_Start);
 
-         m_pTimeTextCtrl_Start = safenew NumericTextCtrl(
-            NumericConverter::TIME, this, ID_TIMETEXT_START);
-         m_pTimeTextCtrl_Start->SetName(_("Start Time"));
-         m_pTimeTextCtrl_Start->SetFormatString(strFormat);
-         m_pTimeTextCtrl_Start->
-            SetValue(wxDateTime_to_AudacityTime(m_DateTime_Start));
-         S.AddWindow(m_pTimeTextCtrl_Start);
-         m_pTimeTextCtrl_Start->EnableMenu(false);
+            m_pTimeTextCtrl_Start = new NumericTextCtrl(
+               NumericConverter::TIME, this, ID_TIMETEXT_START);
+            m_pTimeTextCtrl_Start->SetName(_("Start Time"));
+            m_pTimeTextCtrl_Start->SetFormatString(strFormat);
+            m_pTimeTextCtrl_Start->
+               SetValue(wxDateTime_to_AudacityTime(m_DateTime_Start));
+            S.AddWindow(m_pTimeTextCtrl_Start);
+            m_pTimeTextCtrl_Start->EnableMenu(false);
+         }
+         S.EndStatic();
+
+         S.StartStatic(_("End Date and Time"), true);
+         {
+            m_pDatePickerCtrl_End =
+               new wxDatePickerCtrl(this, // wxWindow *parent,
+               ID_DATEPICKER_END, // wxWindowID id,
+               m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime,
+            // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
+            m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
+            m_pDatePickerCtrl_End->SetName(_("End Date"));
+            S.AddWindow(m_pDatePickerCtrl_End);
+
+            m_pTimeTextCtrl_End = new NumericTextCtrl(
+               NumericConverter::TIME, this, ID_TIMETEXT_END);
+            m_pTimeTextCtrl_End->SetName(_("End Time"));
+            m_pTimeTextCtrl_End->SetFormatString(strFormat);
+            m_pTimeTextCtrl_End->SetValue(wxDateTime_to_AudacityTime(m_DateTime_End));
+            S.AddWindow(m_pTimeTextCtrl_End);
+            m_pTimeTextCtrl_End->EnableMenu(false);
+         }
+         S.EndStatic();
+
+         S.StartStatic(_("Duration"), true);
+         {
+            /* i18n-hint: This string is used to configure the controls which shows the recording
+            * duration. As such it is important that only the alphabetic parts of the string
+            * are translated, with the numbers left exactly as they are.
+            * The string 'days' indicates that the first number in the control will be the number of days,
+            * then the 'h' indicates the second number displayed is hours, the 'm' indicates the third
+            * number displayed is minutes, and the 's' indicates that the fourth number displayed is
+            * seconds.
+            */
+            wxString strFormat1 = _("099 days 024 h 060 m 060 s");
+            m_pTimeTextCtrl_Duration = new NumericTextCtrl(NumericConverter::TIME, this, ID_TIMETEXT_DURATION);
+            m_pTimeTextCtrl_Duration->SetName(_("Duration"));
+            m_pTimeTextCtrl_Duration->SetFormatString(strFormat1);
+            m_pTimeTextCtrl_Duration->SetValue(m_TimeSpan_Duration.GetSeconds().ToDouble());
+            S.AddWindow(m_pTimeTextCtrl_Duration);
+            m_pTimeTextCtrl_Duration->EnableMenu(false);
+         }
+         S.EndStatic();
       }
-      S.EndStatic();
+      S.EndVerticalLay();
 
-      S.StartStatic(_("End Date and Time"), true);
+      S.StartVerticalLay(true);
       {
-         m_pDatePickerCtrl_End =
-            safenew wxDatePickerCtrl(this, // wxWindow *parent,
-                                 ID_DATEPICKER_END, // wxWindowID id,
-                                 m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime,
-                                 // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
-         m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
-         m_pDatePickerCtrl_End->SetName(_("End Date"));
-         S.AddWindow(m_pDatePickerCtrl_End);
+         S.StartStatic(_("Automatic Save"), true);
+         {
+            // If checked, the project will be saved when the recording is completed
+            m_pTimerAutoSaveCheckBoxCtrl = S.Id(ID_AUTOSAVE_CHECKBOX).AddCheckBox(_("Enable &Automatic Save?"),
+                                                                                    (bAutoSave ? "true" : "false"));
+            S.StartMultiColumn(3, wxEXPAND);
+            {
+               wxString sInitialValue = wxT("");
+               AudacityProject* pProject = GetActiveProject();
+               wxString sSaveValue = pProject->GetFileName();
+               if (sSaveValue != wxEmptyString) {
+                  m_fnAutoSaveFile.Assign(sSaveValue);
+                  sInitialValue = _("Current Project");
+               }
+               S.AddPrompt(_("Save Project As:"));
+               m_pTimerSavePathTextCtrl = NewPathControl(this, ID_AUTOSAVEPATH_TEXT, _("Save Project As:"), sInitialValue);
+               m_pTimerSavePathTextCtrl->SetEditable(false);
+               S.AddWindow(m_pTimerSavePathTextCtrl);
+               m_pTimerSavePathButtonCtrl = S.Id(ID_AUTOSAVEPATH_BUTTON).AddButton(_("Select..."));
+               }
+            S.EndMultiColumn();
+         }
+         S.EndStatic();
 
-         m_pTimeTextCtrl_End = safenew NumericTextCtrl(
-            NumericConverter::TIME, this, ID_TIMETEXT_END);
-         m_pTimeTextCtrl_End->SetName(_("End Time"));
-         m_pTimeTextCtrl_End->SetFormatString(strFormat);
-         m_pTimeTextCtrl_End->SetValue(wxDateTime_to_AudacityTime(m_DateTime_End));
-         S.AddWindow(m_pTimeTextCtrl_End);
-         m_pTimeTextCtrl_End->EnableMenu(false);
-      }
-      S.EndStatic();
+         S.StartStatic(_("Automatic Export"), true);
+         {
+            m_pTimerAutoExportCheckBoxCtrl = S.Id(ID_AUTOEXPORT_CHECKBOX).AddCheckBox(_("Enable Automatic &Export?"), (bAutoExport ? "true" : "false"));
+            S.StartMultiColumn(3, wxEXPAND);
+            {
+               S.AddPrompt(_("Export Project As:"));
+               m_pTimerExportPathTextCtrl = NewPathControl(this, ID_AUTOEXPORTPATH_TEXT, _("Export Project As:"), _(""));
+               m_pTimerExportPathTextCtrl->SetEditable(false);
+               S.AddWindow(m_pTimerExportPathTextCtrl);
+               m_pTimerExportPathButtonCtrl = S.Id(ID_AUTOEXPORTPATH_BUTTON).AddButton(_("Select..."));
+            }
+            S.EndMultiColumn();
+         }
+         S.EndStatic();
+
+         S.StartStatic(_("Options"), true);
+         {
+
+            wxArrayString arrayOptions;
+            arrayOptions.Add(_("Do Nothing"));
+            arrayOptions.Add(_("Exit Audacity"));
+            arrayOptions.Add(_("Restart System"));
+            arrayOptions.Add(_("Shutdown System"));
+
+            m_sTimerAfterCompleteOptionsArray.Add(arrayOptions.Item(0));
+            m_sTimerAfterCompleteOptionsArray.Add(arrayOptions.Item(1));
+#ifdef __WINDOWS__
+            m_sTimerAfterCompleteOptionsArray.Add(arrayOptions.Item(2));
+            m_sTimerAfterCompleteOptionsArray.Add(arrayOptions.Item(3));
+#endif
+            m_sTimerAfterCompleteOption = arrayOptions.Item(iPostTimerRecordAction);
+
+            m_pTimerAfterCompleteChoiceCtrl = S.AddChoice(_("After Recording Completes:"),
+                                                          m_sTimerAfterCompleteOption,
+                                                          &m_sTimerAfterCompleteOptionsArray);
+         }
+         S.EndStatic();
 
-      S.StartStatic(_("Duration"), true);
-      {
-         /* i18n-hint: This string is used to configure the controls which shows the recording
-          * duration. As such it is important that only the alphabetic parts of the string
-          * are translated, with the numbers left exactly as they are.
-          * The string 'days' indicates that the first number in the control will be the number of days,
-          * then the 'h' indicates the second number displayed is hours, the 'm' indicates the third
-          * number displayed is minutes, and the 's' indicates that the fourth number displayed is
-          * seconds.
-          */
-         wxString strFormat1 = _("099 days 024 h 060 m 060 s");
-         m_pTimeTextCtrl_Duration = safenew NumericTextCtrl(
-            NumericConverter::TIME, this, ID_TIMETEXT_DURATION);
-         m_pTimeTextCtrl_Duration->SetName(_("Duration"));
-         m_pTimeTextCtrl_Duration->SetFormatString(strFormat1);
-         m_pTimeTextCtrl_Duration->
-            SetValue(m_TimeSpan_Duration.GetSeconds().ToDouble());
-         S.AddWindow(m_pTimeTextCtrl_Duration);
-         m_pTimeTextCtrl_Duration->EnableMenu(false);
       }
-      S.EndStatic();
+      S.EndVerticalLay();
    }
-   S.EndVerticalLay();
+   S.EndMultiColumn();
 
    S.AddStandardButtons();
 
@@ -426,6 +802,9 @@ void TimerRecordDialog::PopulateOrExchange(ShuttleGui& S)
    Fit();
    SetMinSize(GetSize());
    Center();
+
+   EnableDisableAutoControls(bAutoSave, CONTROL_GROUP_SAVE);
+   EnableDisableAutoControls(bAutoExport, CONTROL_GROUP_EXPORT);
 }
 
 bool TimerRecordDialog::TransferDataFromWindow()
@@ -455,6 +834,18 @@ bool TimerRecordDialog::TransferDataFromWindow()
 
    m_TimeSpan_Duration = m_DateTime_End - m_DateTime_Start;
 
+   // Pull the settings from the auto save/export controls and write to the pref file
+   m_bAutoSaveEnabled = m_pTimerAutoSaveCheckBoxCtrl->GetValue();
+   m_bAutoExportEnabled = m_pTimerAutoExportCheckBoxCtrl->GetValue();
+
+   // MY: Obtain the index from the choice control so we can save to the prefs file
+   int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
+
+   // Save the options back to the prefs file
+   gPrefs->Write("/TimerRecord/AutoSave", m_bAutoSaveEnabled);
+   gPrefs->Write("/TimerRecord/AutoExport", m_bAutoExportEnabled);
+   gPrefs->Write("/TimerRecord/PostAction", iPostRecordAction);
+
    return true;
 }
 
@@ -495,9 +886,52 @@ int TimerRecordDialog::WaitForStart()
    bool bIsRecording = false;
    while (updateResult == eProgressSuccess && !bIsRecording)
    {
-      wxMilliSleep(10);
       updateResult = progress.Update();
+      wxMilliSleep(10);
       bIsRecording = (m_DateTime_Start <= wxDateTime::UNow());
    }
    return updateResult;
 }
+
+// TODO: Rather than two flags, an enum with the possibilities would be better.
+int TimerRecordDialog::PreActionDelay(int iActionIndex, bool bSaved, bool bExported)
+{
+   wxString sMessage;
+   wxString sAction = m_pTimerAfterCompleteChoiceCtrl->GetString(iActionIndex);
+   wxString sDone = "";
+   if (bSaved && bExported) {
+      sDone = _("Saved and Exported");
+   }
+   else if (bSaved) {
+      sDone = _("Saved");
+   }
+   else if (bExported) {
+      sDone = _("Exported");
+   }
+   // TODO: The wording will sound better if there are complete messages for 
+   // the will-occur-shortly messages.
+   /* i18n-hint: The first %s will be a translation of 'Saved', 'Exported' or 
+    * 'Saved and Exported'. The second %s will be 'Exit Audacity' 
+    * 'Restart System' or 'Shutdown System' */
+   sMessage.Printf(_("Timer Recording completed: Recording has been %s.\n\n'%s' will occur shortly...\n"),
+                   sDone, sAction);
+
+   wxDateTime dtNow = wxDateTime::UNow();
+   wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
+   wxDateTime dtActionTime = dtNow.Add(tsWait);
+
+   TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
+                          _("Audacity Timer Record - Waiting"),
+                          sMessage,
+                          pdlgHideStopButton);
+
+   int iUpdateResult = eProgressSuccess;
+   bool bIsTime = false;
+   while (iUpdateResult == eProgressSuccess && !bIsTime)
+   {
+      iUpdateResult = dlgAction.Update();
+      wxMilliSleep(10);
+      bIsTime = (dtActionTime <= wxDateTime::UNow());
+   }
+   return iUpdateResult;
+}
diff --git a/src/TimerRecordDialog.h b/src/TimerRecordDialog.h
index 71cb8506f..6dbd8f2c3 100644
--- a/src/TimerRecordDialog.h
+++ b/src/TimerRecordDialog.h
@@ -17,24 +17,46 @@
 #define __AUDACITY_TIMERRECORD_DIALOG__
 
 #include <wx/dialog.h>
+#include <wx/textctrl.h>
 #include <wx/datectrl.h>
 #include <wx/calctrl.h>
 #include <wx/timer.h>
+#include <wx/checkbox.h>
+#include "export/Export.h"
 
 class wxTimerEvent;
 
 class NumericTextCtrl;
 class ShuttleGui;
+class TimerRecordPathCtrl;
+
+class TimerRecordPathCtrl final : public wxTextCtrl
+{
+   // MY: Class that inherits from the wxTextCtrl class.
+   // We override AcceptsFocusFromKeyboard in order to add
+   // the text controls to the Tab Order.
+public:
+   TimerRecordPathCtrl(wxWindow * parent, wxWindowID id, const wxString &value
+      = wxEmptyString, const wxPoint &pos = wxDefaultPosition, const wxSize &
+      size = wxDefaultSize, long  style = 0, const wxValidator &  validator =
+      wxDefaultValidator, const wxString &  name = wxTextCtrlNameStr)
+      :wxTextCtrl(parent, id, value, pos, size, style, validator, name) {};
+   ~TimerRecordPathCtrl() {};
+
+   virtual bool AcceptsFocusFromKeyboard() const override {
+      return true;
+   }
+};
 
 class TimerRecordDialog final : public wxDialog
 {
 public:
-   TimerRecordDialog(wxWindow* parent);
+   TimerRecordDialog(wxWindow* parent, bool bAlreadySaved);
    ~TimerRecordDialog();
 
    void OnTimer(wxTimerEvent& event);
    ///Runs the wait for start dialog.  Returns false if the user clicks stop.
-   bool RunWaitDialog();
+   int RunWaitDialog();
 
 private:
    void OnDatePicker_Start(wxDateEvent& event);
@@ -54,6 +76,25 @@ private:
    void UpdateEnd(); // Update m_DateTime_End and ctrls based on m_DateTime_Start and m_TimeSpan_Duration.
    int WaitForStart();
 
+   // Timer Recording Automation Control Events
+   void OnAutoSavePathButton_Click(wxCommandEvent& event);
+   void OnAutoExportPathButton_Click(wxCommandEvent& event);
+   void OnAutoSaveCheckBox_Change(wxCommandEvent& event);
+   void OnAutoExportCheckBox_Change(wxCommandEvent& event);
+   // Timer Recording Automation Routines
+   void EnableDisableAutoControls(bool bEnable, int iControlGoup);
+   void UpdateTextBoxControls();
+   // Tidy up after Timer Recording
+   bool HaveFilesToRecover();
+   bool RemoveAllAutoSaveFiles();
+
+   // Add Path Controls to Form
+   TimerRecordPathCtrl *NewPathControl(wxWindow *wParent, const int iID, const wxString &sCaption, const wxString &sValue);
+
+   int ExecutePostRecordActions(bool bWasStopped);
+
+   int PreActionDelay(int iActionIndex, bool bSaved, bool bExported);
+
 private:
    wxDateTime m_DateTime_Start;
    wxDateTime m_DateTime_End;
@@ -70,6 +111,34 @@ private:
 
    wxTimer m_timer;
 
+   // Controls for Auto Save/Export
+   wxCheckBox *m_pTimerAutoSaveCheckBoxCtrl;
+   TimerRecordPathCtrl *m_pTimerSavePathTextCtrl;
+   wxButton *m_pTimerSavePathButtonCtrl;
+   wxCheckBox *m_pTimerAutoExportCheckBoxCtrl;
+   TimerRecordPathCtrl *m_pTimerExportPathTextCtrl;
+   wxButton *m_pTimerExportPathButtonCtrl;
+
+   // After Timer Record Options Choice
+   wxChoice *m_pTimerAfterCompleteChoiceCtrl;
+
+   // After Timer Record do we need to clean up?
+   bool m_bProjectCleanupRequired;
+
+   // Variables for the Auto Save/Export
+   bool m_bAutoSaveEnabled;
+   wxFileName m_fnAutoSaveFile;
+   bool m_bAutoExportEnabled;
+   wxFileName m_fnAutoExportFile;
+   int m_iAutoExportFormat;
+   int m_iAutoExportSubFormat;
+   int m_iAutoExportFilterIndex;
+   bool m_bProjectAlreadySaved;
+
+   // Variables for After Timer Recording Option
+   wxString m_sTimerAfterCompleteOption;
+   wxArrayString m_sTimerAfterCompleteOptionsArray;
+
    DECLARE_EVENT_TABLE();
 };
 
diff --git a/src/export/Export.cpp b/src/export/Export.cpp
index 7c4860de9..eca012ce1 100644
--- a/src/export/Export.cpp
+++ b/src/export/Export.cpp
@@ -640,9 +640,9 @@ bool Exporter::GetFilename()
                 !mFilename.FileExists()) {
                // Warn and return to the dialog
                wxMessageBox(_("You are attempting to overwrite an aliased file that is missing.\n\
-The file cannot be written because the path is needed to restore the original audio to the project.\n\
-Choose File > Check Dependencies to view the locations of all missing files.\n\
-If you still wish to export, please choose a different filename or folder."));
+               The file cannot be written because the path is needed to restore the original audio to the project.\n\
+               Choose File > Check Dependencies to view the locations of all missing files.\n\
+               If you still wish to export, please choose a different filename or folder."));
                overwritingMissingAlias = true;
             }
          }
@@ -886,6 +886,88 @@ void Exporter::OnFilterChanged(wxFileCtrlEvent & evt)
    mBook->ChangeSelection(index);
 }
 
+bool Exporter::ProcessFromTimerRecording(AudacityProject *project,
+                                         bool selectedOnly,
+                                         double t0,
+                                         double t1,
+                                         wxFileName fnFile,
+                                         int iFormat,
+                                         int iSubFormat,
+                                         int iFilterIndex)
+{
+   // Save parms
+   mProject = project;
+   mSelectedOnly = selectedOnly;
+   mT0 = t0;
+   mT1 = t1;
+
+   // Auto Export Parameters
+   mFilename = fnFile;
+   mFormat = iFormat;
+   mSubFormat = iSubFormat;
+   mFilterIndex = iFilterIndex;
+
+   // Gather track information
+   if (!ExamineTracks()) {
+      return false;
+   }
+
+   // Check for down mixing
+   if (!CheckMix()) {
+      return false;
+   }
+
+   // Ensure filename doesn't interfere with project files.
+   if (!CheckFilename()) {
+      return false;
+   }
+
+   // Export the tracks
+   bool success = ExportTracks();
+
+   // Get rid of mixerspec
+   if (mMixerSpec) {
+      delete mMixerSpec;
+      mMixerSpec = NULL;
+   }
+
+   return success;
+}
+
+int Exporter::GetAutoExportFormat() {
+   return mFormat;
+}
+
+int Exporter::GetAutoExportSubFormat() {
+   return mSubFormat;
+}
+
+int Exporter::GetAutoExportFilterIndex() {
+   return mFormat;
+}
+
+wxFileName Exporter::GetAutoExportFileName() {
+   return mFilename;
+}
+
+bool Exporter::SetAutoExportOptions(AudacityProject *project) {
+   mFormat = -1;
+   mProject = project;
+
+   if( GetFilename()==false )
+        return false;
+
+   // Let user edit MetaData
+   if (mPlugins[mFormat]->GetCanMetaData(mSubFormat)) {
+      if (!(project->DoEditMetadata(_("Edit Metadata Tags for Export"),
+                                    _("Exported Tags"), mProject->GetShowId3Dialog()))) {
+         return false;
+      }
+   }
+
+   return true;
+}
+
 //----------------------------------------------------------------------------
 // ExportMixerPanel
 //----------------------------------------------------------------------------
diff --git a/src/export/Export.h b/src/export/Export.h
index 9bd50b1be..7964ca8d9 100644
--- a/src/export/Export.h
+++ b/src/export/Export.h
@@ -153,6 +153,21 @@ public:
 
    const ExportPluginArray GetPlugins();
 
+   // Auto Export from Timer Recording
+   bool ProcessFromTimerRecording(AudacityProject *project,
+                                  bool selectedOnly,
+                                  double t0,
+                                  double t1,
+                                  wxFileName fnFile,
+                                  int iFormat,
+                                  int iSubFormat,
+                                  int iFilterIndex);
+   bool SetAutoExportOptions(AudacityProject *project);
+   int GetAutoExportFormat();
+   int GetAutoExportSubFormat();
+   int GetAutoExportFilterIndex();
+   wxFileName GetAutoExportFileName();
+
 private:
 
    bool ExamineTracks();
diff --git a/src/widgets/ProgressDialog.cpp b/src/widgets/ProgressDialog.cpp
index 73b2f1f79..64c0bb2b3 100644
--- a/src/widgets/ProgressDialog.cpp
+++ b/src/widgets/ProgressDialog.cpp
@@ -1569,7 +1569,14 @@ int TimerProgressDialog::Update(const wxString & message /*= wxEmptyString*/)
    // From testing, it's never shown bigger than 1009, but 
    // give it a little extra, to 1010. 
    //   wxASSERT((nGaugeValue >= 0) && (nGaugeValue <= 1000)); // This ought to work. 
-   wxASSERT((nGaugeValue >= 0) && (nGaugeValue <= 1010));
+   // wxASSERT((nGaugeValue >= 0) && (nGaugeValue <= 1010));
+   //
+   // stf. Update was being called after wxMilliSleep(<ms>), which could be up to <ms>
+   // beyond the completion time. My gusess is that the microsleep in RunWaitDialog was originally 10 ms
+   // (same as other uses of Update) but was updated to kTimerInterval = 50 ms, thus triggering
+   // the Assert (Bug 1367). By calling Update() before sleeping then I think nGaugeValue <= 1000 should work.
+   wxASSERT((nGaugeValue >= 0) && (nGaugeValue <= 1000));
+
    if (nGaugeValue != mLastValue)
    {
       mGauge->SetValue(nGaugeValue);