Audacity 3.2.0
Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
TimerRecordDialog Class Referencefinal

Dialog for Timer Record, i.e., timed or long recording. More...

#include <TimerRecordDialog.h>

Inheritance diagram for TimerRecordDialog:
[legend]
Collaboration diagram for TimerRecordDialog:
[legend]

Public Types

using ProgressResult = BasicUI::ProgressResult
 

Public Member Functions

 TimerRecordDialog (wxWindow *parent, AudacityProject &project, bool bAlreadySaved)
 
 ~TimerRecordDialog ()
 
void OnTimer (wxTimerEvent &event)
 
int RunWaitDialog ()
 Runs the wait for start dialog. Returns false if the user clicks stop. More...
 
- Public Member Functions inherited from wxDialogWrapper
 wxDialogWrapper ()
 
 wxDialogWrapper (wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const TranslatableString &name=XO("Dialog"))
 
bool Create (wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const TranslatableString &name=XO("Dialog"))
 
void SetTitle (const TranslatableString &title)
 
void SetLabel (const TranslatableString &title)
 
void SetName (const TranslatableString &title)
 
void SetName ()
 
- Public Member Functions inherited from wxTabTraversalWrapper< wxDialog >
 wxTabTraversalWrapper (Args &&... args)
 
 wxTabTraversalWrapper (const wxTabTraversalWrapper &)=delete
 
 wxTabTraversalWrapper (wxTabTraversalWrapper &&)=delete
 
wxTabTraversalWrapperoperator= (const wxTabTraversalWrapper &)=delete
 
wxTabTraversalWrapperoperator= (wxTabTraversalWrapper &&)=delete
 

Private Member Functions

void OnDatePicker_Start (wxDateEvent &event)
 
void OnTimeText_Start (wxCommandEvent &event)
 
void OnDatePicker_End (wxDateEvent &event)
 
void OnTimeText_End (wxCommandEvent &event)
 
void OnTimeText_Duration (wxCommandEvent &event)
 
void OnOK (wxCommandEvent &event)
 
void OnHelpButtonClick (wxCommandEvent &event)
 
TranslatableString GetDisplayDate (wxDateTime &dt)
 
void PopulateOrExchange (ShuttleGui &S)
 
bool TransferDataFromWindow () override
 
void UpdateDuration ()
 
void UpdateEnd ()
 
ProgressResult WaitForStart ()
 
void OnAutoSavePathButton_Click (wxCommandEvent &event)
 
void OnAutoExportPathButton_Click (wxCommandEvent &event)
 
void OnAutoSaveCheckBox_Change (wxCommandEvent &event)
 
void OnAutoExportCheckBox_Change (wxCommandEvent &event)
 
void EnableDisableAutoControls (bool bEnable, int iControlGoup)
 
void UpdateTextBoxControls ()
 
wxTextCtrlWrapperNewPathControl (wxWindow *wParent, const int iID, const TranslatableString &sCaption, const TranslatableString &sValue)
 
int ExecutePostRecordActions (bool bWasStopped)
 
ProgressResult PreActionDelay (int iActionIndex, TimerRecordCompletedActions eCompletedActions)
 

Private Attributes

AudacityProjectmProject
 
wxDateTime m_DateTime_Start
 
wxDateTime m_DateTime_End
 
wxTimeSpan m_TimeSpan_Duration
 
wxDatePickerCtrl * m_pDatePickerCtrl_Start
 
NumericTextCtrlm_pTimeTextCtrl_Start
 
wxDatePickerCtrl * m_pDatePickerCtrl_End
 
NumericTextCtrlm_pTimeTextCtrl_End
 
NumericTextCtrlm_pTimeTextCtrl_Duration
 
wxTimer m_timer
 
wxCheckBox * m_pTimerAutoSaveCheckBoxCtrl
 
wxTextCtrlWrapperm_pTimerSavePathTextCtrl
 
wxButton * m_pTimerSavePathButtonCtrl
 
wxCheckBox * m_pTimerAutoExportCheckBoxCtrl
 
wxTextCtrlWrapperm_pTimerExportPathTextCtrl
 
wxButton * m_pTimerExportPathButtonCtrl
 
wxChoice * m_pTimerAfterCompleteChoiceCtrl
 
bool m_bProjectCleanupRequired
 
bool m_bAutoSaveEnabled
 
wxFileName m_fnAutoSaveFile
 
bool m_bAutoExportEnabled
 
wxFileName m_fnAutoExportFile
 
wxString m_sAutoExportFormat
 
int m_iAutoExportSampleRate {0}
 
int m_iAutoExportChannels {0}
 
ExportProcessor::Parameters m_AutoExportParameters
 
bool m_bProjectAlreadySaved
 

Detailed Description

Dialog for Timer Record, i.e., timed or long recording.

Definition at line 57 of file TimerRecordDialog.h.

Member Typedef Documentation

◆ ProgressResult

Definition at line 60 of file TimerRecordDialog.h.

Constructor & Destructor Documentation

◆ TimerRecordDialog()

TimerRecordDialog::TimerRecordDialog ( wxWindow *  parent,
AudacityProject project,
bool  bAlreadySaved 
)

Definition at line 168 of file TimerRecordDialog.cpp.

170: wxDialogWrapper(parent, -1, XO("Audacity Timer Record"), wxDefaultPosition,
171 wxDefaultSize, wxCAPTION)
172, mProject{ project }
173{
174 SetName();
175
176 m_DateTime_Start = wxDateTime::UNow();
177 long seconds; // default duration is 1 hour = 3600 seconds
178 gPrefs->Read(wxT("/TimerRecord/LastDuration"), &seconds, 3600L);
179 m_TimeSpan_Duration = wxTimeSpan::Seconds(seconds);
181
184
186 m_pTimeTextCtrl_End = NULL;
187
189
190 // Do we allow the user to change the Automatic Save file?
191 m_bProjectAlreadySaved = bAlreadySaved;
192
193 wxString exportPath;
194 DefaultExportAudioPath.Read(&exportPath);
195 if(exportPath.empty())
196 exportPath = FileNames::FindDefaultPath(FileNames::Operation::Export);
197 m_fnAutoExportFile.SetPath(exportPath);
198
200 if(m_fnAutoExportFile.GetName().IsEmpty())
201 m_fnAutoExportFile.SetName(_("untitled"));
202
204 if(!m_sAutoExportFormat.empty())
205 {
206 auto [plugin, formatIndex]
208
209 if(plugin != nullptr)
210 {
211 const auto formatInfo = plugin->GetFormatInfo(formatIndex);
212 m_fnAutoExportFile.SetExt(formatInfo.extensions[0]);
213 }
214 }
215
218
219 ShuttleGui S(this, eIsCreating);
220 this->PopulateOrExchange(S);
221
222 // Set initial focus to "1" of "01h" in Duration NumericTextCtrl,
223 // instead of OK button (default).
224 m_pTimeTextCtrl_Duration->SetFocus();
226
227 m_timer.SetOwner(this, TIMER_ID);
229}
wxT("CloseDown"))
IntSetting AudioIORecordChannels
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
@ eIsCreating
Definition: ShuttleGui.h:37
const auto project
const int kSlowTimerInterval
#define TIMER_ID
#define S(N)
Definition: ToChars.cpp:64
const wxString & GetProjectName() const
Definition: Project.cpp:100
std::tuple< ExportPlugin *, int > FindFormat(const wxString &format, bool compareWithCase=false) const
Returns first pair of [exportPlugin, formatIndex], such that: exportPlugin->GetFormatInfo(formatIndex...
static ExportPluginRegistry & Get()
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
wxDatePickerCtrl * m_pDatePickerCtrl_Start
NumericTextCtrl * m_pTimeTextCtrl_Duration
NumericTextCtrl * m_pTimeTextCtrl_End
AudacityProject & mProject
void PopulateOrExchange(ShuttleGui &S)
NumericTextCtrl * m_pTimeTextCtrl_Start
wxDateTime m_DateTime_Start
wxFileName m_fnAutoExportFile
wxTimeSpan m_TimeSpan_Duration
wxDatePickerCtrl * m_pDatePickerCtrl_End
virtual bool Read(const wxString &key, bool *value) const =0
FILES_API FilePath FindDefaultPath(Operation op)

References project.

◆ ~TimerRecordDialog()

TimerRecordDialog::~TimerRecordDialog ( )
default

Member Function Documentation

◆ EnableDisableAutoControls()

void TimerRecordDialog::EnableDisableAutoControls ( bool  bEnable,
int  iControlGoup 
)
private

Definition at line 490 of file TimerRecordDialog.cpp.

490 {
491
492 if (iControlGoup == CONTROL_GROUP_EXPORT) {
493 m_pTimerExportPathTextCtrl->Enable( bEnable );
494 m_pTimerExportPathButtonCtrl->Enable( bEnable);
495 } else if (iControlGoup == CONTROL_GROUP_SAVE) {
496 m_pTimerSavePathTextCtrl->Enable( bEnable);
497 m_pTimerSavePathButtonCtrl->Enable(bEnable );
498 }
499
500 // Enable or disable the Choice box - if there is no Save or Export then this will be disabled
501 if (m_pTimerAutoSaveCheckBoxCtrl->GetValue() || m_pTimerAutoExportCheckBoxCtrl->GetValue()) {
503 } else {
506 }
507}
@ CONTROL_GROUP_SAVE
@ CONTROL_GROUP_EXPORT
@ POST_TIMER_RECORD_NOTHING
wxButton * m_pTimerSavePathButtonCtrl
wxCheckBox * m_pTimerAutoSaveCheckBoxCtrl
wxTextCtrlWrapper * m_pTimerExportPathTextCtrl
wxChoice * m_pTimerAfterCompleteChoiceCtrl
wxCheckBox * m_pTimerAutoExportCheckBoxCtrl
wxTextCtrlWrapper * m_pTimerSavePathTextCtrl
wxButton * m_pTimerExportPathButtonCtrl

References CONTROL_GROUP_EXPORT, CONTROL_GROUP_SAVE, m_pTimerAfterCompleteChoiceCtrl, m_pTimerAutoExportCheckBoxCtrl, m_pTimerAutoSaveCheckBoxCtrl, m_pTimerExportPathButtonCtrl, m_pTimerExportPathTextCtrl, m_pTimerSavePathButtonCtrl, m_pTimerSavePathTextCtrl, and POST_TIMER_RECORD_NOTHING.

Referenced by OnAutoExportCheckBox_Change(), OnAutoSaveCheckBox_Change(), and PopulateOrExchange().

Here is the caller graph for this function:

◆ ExecutePostRecordActions()

int TimerRecordDialog::ExecutePostRecordActions ( bool  bWasStopped)
private

Definition at line 599 of file TimerRecordDialog.cpp.

599 {
600 // MY: We no longer automatically (and silently) call ->Save() when the
601 // timer recording is completed. We can now Save and/or Export depending
602 // on the options selected by the user.
603 // Once completed, we can also close Audacity, restart the system or
604 // shutdown the system.
605 // If there was any error with the auto save or export then we will not do
606 // the actions requested and instead present an error mesasge to the user.
607 // Finally, if there is no post-record action selected then we output
608 // a dialog detailing what has been carried out instead.
609
610 bool bSaveOK = false;
611 bool bExportOK = false;
612 int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
613 int iOverriddenAction = iPostRecordAction;
614 bool bErrorOverride = false;
615
616 // Do Automatic Save?
617 if (m_bAutoSaveEnabled) {
618
619 auto &projectFileManager = ProjectFileManager::Get( mProject );
620 // MY: If this project has already been saved then simply execute a Save here
622 bSaveOK = projectFileManager.Save();
623 } else {
624 bSaveOK = projectFileManager.SaveFromTimerRecording(m_fnAutoSaveFile);
625 }
626 }
627
628 // Do Automatic Export?
630 const auto& tracks = TrackList::Get(mProject);
631 if(ExportUtils::FindExportWaveTracks(tracks, false).empty())
632 {
633 ShowExportErrorDialog(XO("All audio is muted."), XO("Warning"), false);
634 bExportOK = true;
635 }
636 else
637 {
638 const auto t0 = std::max(.0, tracks.GetStartTime());
639
640 auto [exportPlugin, formatIndex] =
642
643 if(exportPlugin != nullptr)
644 {
645 auto builder = ExportTaskBuilder {}
648 .SetRange(t0, tracks.GetEndTime(), false)
651 .SetPlugin(exportPlugin, formatIndex);
652
654 {
655 const auto result = ExportProgressUI::Show(builder.Build(mProject));
656 bExportOK = result == ExportResult::Success ||
657 result == ExportResult::Stopped;
658 });
659
660 if(bExportOK)
661 {
664 }
665 }
666 }
667 }
668
669 // Check if we need to override the post recording action
670 bErrorOverride = ((m_bAutoSaveEnabled && !bSaveOK) || (m_bAutoExportEnabled && !bExportOK));
671 if (bErrorOverride || bWasStopped) {
672 iPostRecordAction = POST_TIMER_RECORD_NOTHING;
673 }
674
675 if (iPostRecordAction == POST_TIMER_RECORD_NOTHING) {
676 // If there is no post-record action then we can show a message indicating what has been done
677
678 auto sMessage = (bWasStopped ? XO("Timer Recording stopped.") :
679 XO("Timer Recording completed."));
680
681 if (m_bAutoSaveEnabled) {
682 if (bSaveOK) {
683 sMessage = XO("%s\n\nRecording saved: %s").Format(
684 sMessage, m_fnAutoSaveFile.GetFullPath());
685 } else {
686 sMessage = XO("%s\n\nError saving recording.").Format( sMessage );
687 }
688 }
690 if (bExportOK) {
691 sMessage = XO("%s\n\nRecording exported: %s").Format(
692 sMessage, m_fnAutoExportFile.GetFullPath());
693 } else {
694 sMessage = XO("%s\n\nError exporting recording.").Format( sMessage );
695 }
696 }
697
698 if (bErrorOverride) {
699
700 if ((iOverriddenAction != iPostRecordAction) &&
701 (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
702 // Inform the user that we have overridden the selected action
703 sMessage = XO("%s\n\n'%s' has been canceled due to the error(s) noted above.").Format(
704 sMessage,
705 m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
706 }
707
708 // Show Error Message Box
710 sMessage,
711 XO("Error"),
712 wxICON_EXCLAMATION | wxOK);
713 } else {
714
715 if (bWasStopped && (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
716 sMessage = XO("%s\n\n'%s' has been canceled as the recording was stopped.").Format(
717 sMessage,
718 m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
719 }
720
722 sMessage,
723 XO("Timer Recording"),
724 wxICON_INFORMATION | wxOK);
725 }
726 }
727
728 // MY: Lets do some actions that only apply to Exit/Restart/Shutdown
729 if (iPostRecordAction >= POST_TIMER_RECORD_CLOSE) {
730 do {
731
732 // Set the flags as appropriate based on what we have done
733 wxUint32 eActionFlags = TR_ACTION_NOTHING;
734 if (m_bAutoSaveEnabled && bSaveOK) {
735 eActionFlags |= TR_ACTION_SAVED;
736 }
737 if (m_bAutoExportEnabled && bExportOK) {
738 eActionFlags |= TR_ACTION_EXPORTED;
739 }
740
741 // Lets show a warning dialog telling the user what is about to happen.
742 // If the user no longer wants to carry out this action then they can click
743 // Cancel and we will do POST_TIMER_RECORD_NOTHING instead.
744 auto iDelayOutcome = PreActionDelay(iPostRecordAction, (TimerRecordCompletedActions)eActionFlags);
745 if (iDelayOutcome != ProgressResult::Success) {
746 // Cancel the action!
747 iPostRecordAction = POST_TIMER_RECORD_NOTHING;
748 break;
749 }
750 } while (false);
751 }
752
753 // Return the action as required
754 return iPostRecordAction;
755}
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
void ShowExportErrorDialog(const TranslatableString &message, const TranslatableString &caption, bool allowReporting)
Definition: Export.cpp:144
const auto tracks
TimerRecordCompletedActions
@ TR_ACTION_NOTHING
@ TR_ACTION_EXPORTED
@ TR_ACTION_SAVED
@ POST_TIMER_RECORD_CLOSE
ExportTaskBuilder & SetPlugin(const ExportPlugin *plugin, int format=0) noexcept
Definition: Export.cpp:59
ExportTaskBuilder & SetParameters(ExportProcessor::Parameters parameters) noexcept
Definition: Export.cpp:47
ExportTaskBuilder & SetNumChannels(unsigned numChannels) noexcept
Definition: Export.cpp:53
ExportTaskBuilder & SetSampleRate(double sampleRate) noexcept
Definition: Export.cpp:72
ExportTaskBuilder & SetFileName(const wxFileName &filename)
Definition: Export.cpp:33
ExportTaskBuilder & SetRange(double t0, double t1, bool selectedOnly=false) noexcept
Definition: Export.cpp:39
static TrackIterRange< const WaveTrack > FindExportWaveTracks(const TrackList &tracks, bool selectedOnly)
Definition: ExportUtils.cpp:23
static ProjectFileManager & Get(AudacityProject &project)
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:259
wxFileName m_fnAutoSaveFile
ExportProcessor::Parameters m_AutoExportParameters
ProgressResult PreActionDelay(int iActionIndex, TimerRecordCompletedActions eCompletedActions)
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
IMPORT_EXPORT_API ExportResult Show(ExportTask exportTask)
void ExceptionWrappedCall(Callable callable)

References AudacityMessageBox(), anonymous_namespace{TimerRecordDialog.cpp}::DefaultExportAudioFormat, anonymous_namespace{TimerRecordDialog.cpp}::DefaultExportAudioPath, ExportProgressUI::ExceptionWrappedCall(), ExportUtils::FindExportWaveTracks(), ExportPluginRegistry::FindFormat(), ExportPluginRegistry::Get(), TrackList::Get(), ProjectFileManager::Get(), m_AutoExportParameters, m_bAutoExportEnabled, m_bAutoSaveEnabled, m_bProjectAlreadySaved, m_fnAutoExportFile, m_fnAutoSaveFile, m_iAutoExportChannels, m_iAutoExportSampleRate, m_pTimerAfterCompleteChoiceCtrl, m_sAutoExportFormat, mProject, POST_TIMER_RECORD_CLOSE, POST_TIMER_RECORD_NOTHING, PreActionDelay(), ExportTaskBuilder::SetFileName(), ExportTaskBuilder::SetNumChannels(), ExportTaskBuilder::SetParameters(), ExportTaskBuilder::SetPlugin(), ExportTaskBuilder::SetRange(), ExportTaskBuilder::SetSampleRate(), ExportProgressUI::Show(), ShowExportErrorDialog(), Stopped, BasicUI::Success, Success, TR_ACTION_EXPORTED, TR_ACTION_NOTHING, TR_ACTION_SAVED, tracks, Setting< T >::Write(), and XO().

Referenced by RunWaitDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetDisplayDate()

TranslatableString TimerRecordDialog::GetDisplayDate ( wxDateTime &  dt)
private

Definition at line 757 of file TimerRecordDialog.cpp.

758{
759#if defined(__WXMSW__)
760 // On Windows, wxWidgets uses the system date control and it displays the
761 // date based on the Windows locale selected by the user. But, wxDateTime
762 // using the strftime function to return the formatted date. Since the
763 // default locale for the Windows CRT environment is "C", the dates come
764 // back in a different format.
765 //
766 // So, we make direct Windows calls to format the date like it the date
767 // control.
768 //
769 // (Most of this taken from src/msw/datectrl.cpp)
770
771 const wxDateTime::Tm tm(dt.GetTm());
772 SYSTEMTIME st;
773 wxString s;
774 int len;
775
776 st.wYear = (WXWORD)tm.year;
777 st.wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1);
778 st.wDay = tm.mday;
779 st.wDayOfWeek = st.wMinute = st.wSecond = st.wMilliseconds = 0;
780
781 len = ::GetDateFormat(LOCALE_USER_DEFAULT,
782 DATE_SHORTDATE,
783 &st,
784 NULL,
785 NULL,
786 0);
787 if (len > 0) {
788 len = ::GetDateFormat(LOCALE_USER_DEFAULT,
789 DATE_SHORTDATE,
790 &st,
791 NULL,
792 wxStringBuffer(s, len),
793 len);
794 if (len > 0) {
795 s += wxT(" ") + dt.FormatTime();
796 return Verbatim( s );
797 }
798 }
799#endif
800
801 // Use default formatting
802wxPrintf(wxT("%s\n"), dt.Format());
803 return Verbatim( dt.FormatDate() + wxT(" ") + dt.FormatTime() );
804}
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.

References Verbatim(), and wxT().

Referenced by RunWaitDialog(), and WaitForStart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ NewPathControl()

wxTextCtrlWrapper * TimerRecordDialog::NewPathControl ( wxWindow *  wParent,
const int  iID,
const TranslatableString sCaption,
const TranslatableString sValue 
)
private

Definition at line 806 of file TimerRecordDialog.cpp.

809{
810 wxTextCtrlWrapper * pTextCtrl;
811 wxASSERT(wParent); // to justify safenew
812 pTextCtrl = safenew wxTextCtrlWrapper(wParent, iID, sValue.Translation());
813 pTextCtrl->SetName(sCaption.Translation());
814 return pTextCtrl;
815}
#define safenew
Definition: MemoryX.h:10
wxString Translation() const

References safenew, and TranslatableString::Translation().

Referenced by PopulateOrExchange().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnAutoExportCheckBox_Change()

void TimerRecordDialog::OnAutoExportCheckBox_Change ( wxCommandEvent &  event)
private

Definition at line 402 of file TimerRecordDialog.cpp.

402 {
404}
void EnableDisableAutoControls(bool bEnable, int iControlGoup)

References CONTROL_GROUP_EXPORT, EnableDisableAutoControls(), and m_pTimerAutoExportCheckBoxCtrl.

Here is the call graph for this function:

◆ OnAutoExportPathButton_Click()

void TimerRecordDialog::OnAutoExportPathButton_Click ( wxCommandEvent &  event)
private

Definition at line 378 of file TimerRecordDialog.cpp.

379{
380 // Set the options required
381 TimerRecordExportDialog exportDialog(mProject, this);
382 exportDialog.Bind(
388
389 if(exportDialog.ShowModal() != wxID_OK)
390 return;
391
392 m_pTimerExportPathTextCtrl->SetValue(m_fnAutoExportFile.GetFullPath());
393
394 // Update the text controls
395 this->UpdateTextBoxControls();
396}

References TimerRecordExportDialog::Bind(), m_AutoExportParameters, m_fnAutoExportFile, m_iAutoExportChannels, m_iAutoExportSampleRate, m_pTimerExportPathTextCtrl, m_sAutoExportFormat, mProject, and UpdateTextBoxControls().

Here is the call graph for this function:

◆ OnAutoSaveCheckBox_Change()

void TimerRecordDialog::OnAutoSaveCheckBox_Change ( wxCommandEvent &  event)
private

Definition at line 398 of file TimerRecordDialog.cpp.

References CONTROL_GROUP_SAVE, EnableDisableAutoControls(), and m_pTimerAutoSaveCheckBoxCtrl.

Here is the call graph for this function:

◆ OnAutoSavePathButton_Click()

void TimerRecordDialog::OnAutoSavePathButton_Click ( wxCommandEvent &  event)
private

Definition at line 340 of file TimerRecordDialog.cpp.

341{
342 auto &projectFileIO = ProjectFileIO::Get(mProject);
343
344 wxString fName = SelectFile(FileNames::Operation::Export,
345 XO("Save Timer Recording As"),
346 m_fnAutoSaveFile.GetPath(),
347 m_fnAutoSaveFile.GetFullName(),
348 wxT("aup3"),
350 wxFD_SAVE | wxRESIZE_BORDER,
351 this);
352
353 if (fName.empty())
354 return;
355
356 // If project already exists then abort - we do not allow users to overwrite an existing project
357 // unless it is the current project.
358 if (wxFileExists(fName) && (projectFileIO.GetFileName() != fName)) {
360 nullptr,
361 XO("The selected file name could not be used\nfor Timer Recording because it \
362would overwrite another project.\nPlease try again and select an original name."),
363 XO("Error Saving Timer Recording Project"),
364 wxOK|wxICON_ERROR );
365 m.ShowModal();
366 return;
367 }
368
369 // Set this boolean to false so we now do a SaveAs at the end of the recording
370 // unless we're saving the current project.
371 m_bProjectAlreadySaved = projectFileIO.GetFileName() == fName? true : false;
372
373 m_fnAutoSaveFile = fName;
374 m_fnAutoSaveFile.SetExt(wxT("aup3"));
375 this->UpdateTextBoxControls();
376}
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
Wrap wxMessageDialog so that caption IS translatable.
FILES_API const FileType AudacityProjects
Definition: FileNames.h:71
static ProjectFileIO & Get(AudacityProject &project)

References FileNames::AudacityProjects, ProjectFileIO::Get(), m_bProjectAlreadySaved, m_fnAutoSaveFile, mProject, SelectFile(), UpdateTextBoxControls(), wxT(), and XO().

Here is the call graph for this function:

◆ OnDatePicker_End()

void TimerRecordDialog::OnDatePicker_End ( wxDateEvent &  event)
private

Definition at line 286 of file TimerRecordDialog.cpp.

287{
289 double dTime = m_pTimeTextCtrl_End->GetValue();
290 long hr = (long)(dTime / 3600.0);
291 long min = (long)((dTime - (hr * 3600.0)) / 60.0);
292 long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
293 m_DateTime_End.SetHour(hr);
294 m_DateTime_End.SetMinute(min);
295 m_DateTime_End.SetSecond(sec);
296
297 // DatePickerCtrls use SetRange to make sure End is never less than Start, but
298 // need to implement it for the TimeTextCtrls.
303 }
304
305 this->UpdateDuration(); // Keep Start constant and update Duration for changed End.
306}
int min(int a, int b)
static double wxDateTime_to_AudacityTime(wxDateTime &dateTime)
void SetValue(double newValue)

References NumericConverter::GetValue(), m_DateTime_End, m_DateTime_Start, m_pDatePickerCtrl_End, m_pTimeTextCtrl_End, min(), NumericTextCtrl::SetValue(), UpdateDuration(), and wxDateTime_to_AudacityTime().

Referenced by OnTimeText_End().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnDatePicker_Start()

void TimerRecordDialog::OnDatePicker_Start ( wxDateEvent &  event)
private

Definition at line 244 of file TimerRecordDialog.cpp.

245{
247 double dTime = m_pTimeTextCtrl_Start->GetValue();
248 long hr = (long)(dTime / 3600.0);
249 long min = (long)((dTime - (hr * 3600.0)) / 60.0);
250 long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
251 m_DateTime_Start.SetHour(hr);
252 m_DateTime_Start.SetMinute(min);
253 m_DateTime_Start.SetSecond(sec);
254
255 // User might have had the dialog up for a while, or
256 // had a future day, set hour of day less than now's, then changed day to today.
257 wxTimerEvent dummyTimerEvent;
258 this->OnTimer(dummyTimerEvent);
259
260 // Always update End for changed Start, keeping Duration constant.
261 // Note that OnTimer sometimes calls UpdateEnd, so sometimes this is redundant,
262 // but OnTimer doesn't need to always call UpdateEnd, but we must here.
263 this->UpdateEnd();
264}
void OnTimer(wxTimerEvent &event)

References NumericConverter::GetValue(), m_DateTime_Start, m_pDatePickerCtrl_Start, m_pTimeTextCtrl_Start, min(), OnTimer(), and UpdateEnd().

Referenced by OnTimeText_Start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnHelpButtonClick()

void TimerRecordDialog::OnHelpButtonClick ( wxCommandEvent &  event)
private

Definition at line 406 of file TimerRecordDialog.cpp.

407{
408 HelpSystem::ShowHelp(this, L"Timer_Record", true);
409}
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:231

References HelpSystem::ShowHelp().

Here is the call graph for this function:

◆ OnOK()

void TimerRecordDialog::OnOK ( wxCommandEvent &  event)
private

Definition at line 411 of file TimerRecordDialog.cpp.

412{
414 if (!m_TimeSpan_Duration.IsPositive())
415 {
417 XO("Duration is zero. Nothing will be recorded."),
418 XO("Error in Duration"),
419 wxICON_EXCLAMATION | wxOK);
420 return;
421 }
422
423 // Validate that we have a Save and/or Export path setup if the appropriate check box is ticked
424 wxString sTemp = m_fnAutoSaveFile.GetFullPath();
425 if (m_pTimerAutoSaveCheckBoxCtrl->IsChecked()) {
426 if (!m_fnAutoSaveFile.IsOk() || m_fnAutoSaveFile.IsDir()) {
428 XO("Automatic Save path is invalid."),
429 XO("Error in Automatic Save"),
430 wxICON_EXCLAMATION | wxOK);
431 return;
432 }
433 }
434 if (m_pTimerAutoExportCheckBoxCtrl->IsChecked()) {
435 if (!m_fnAutoExportFile.IsOk() || m_fnAutoExportFile.IsDir()) {
437 XO("Automatic Export path is invalid."),
438 XO("Error in Automatic Export"),
439 wxICON_EXCLAMATION | wxOK);
440 return;
441 }
442 }
443
444 // MY: Estimate here if we have enough disk space to
445 // complete this Timer Recording.
446 // If we don't think there is enough space then ask the user
447 // if they want to continue.
448 // We don't stop the user from starting the recording
449 // as its possible that they plan to free up some
450 // space before the recording begins
451 auto &projectManager = ProjectManager::Get( mProject );
452
453 // How many minutes do we have left on the disc?
454 int iMinsLeft = projectManager.GetEstimatedRecordingMinsLeftOnDisk();
455
456 // How many minutes will this recording require?
457 int iMinsRecording = m_TimeSpan_Duration.GetMinutes();
458
459 // Do we have enough space?
460 if (iMinsRecording >= iMinsLeft) {
461
462 // Format the strings
463 auto sRemainingTime = projectManager.GetHoursMinsString(iMinsLeft);
464 auto sPlannedTime = projectManager.GetHoursMinsString(iMinsRecording);
465
466 // Create the message string
467 auto sMessage = XO(
468"You may not have enough free disk space to complete this Timer Recording, based on your current settings.\n\nDo you wish to continue?\n\nPlanned recording duration: %s\nRecording time remaining on disk: %s")
469 .Format( sPlannedTime, sRemainingTime );
470
471 AudacityMessageDialog dlgMessage(
472 nullptr,
473 sMessage,
474 XO("Timer Recording Disk Space Warning"),
475 wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
476 if (dlgMessage.ShowModal() != wxID_YES ) {
477 // User decided not to continue - bail out!
478 return;
479 }
480 }
481
482 m_timer.Stop(); // Don't need to keep updating m_DateTime_Start to prevent backdating.
483 this->EndModal(wxID_OK);
484 wxLongLong duration = m_TimeSpan_Duration.GetSeconds();
485 // this will assert if the duration won't fit in a long
486 gPrefs->Write(wxT("/TimerRecord/LastDuration"), duration.ToLong());
487 gPrefs->Flush();
488}
static ProjectManager & Get(AudacityProject &project)
bool TransferDataFromWindow() override
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0

References AudacityMessageBox(), audacity::BasicSettings::Flush(), ProjectManager::Get(), gPrefs, m_fnAutoExportFile, m_fnAutoSaveFile, m_pTimerAutoExportCheckBoxCtrl, m_pTimerAutoSaveCheckBoxCtrl, m_timer, m_TimeSpan_Duration, mProject, TransferDataFromWindow(), audacity::BasicSettings::Write(), wxT(), and XO().

Here is the call graph for this function:

◆ OnTimer()

void TimerRecordDialog::OnTimer ( wxTimerEvent &  event)

Definition at line 233 of file TimerRecordDialog.cpp.

234{
235 wxDateTime dateTime_UNow = wxDateTime::UNow();
236 if (m_DateTime_Start < dateTime_UNow) {
237 m_DateTime_Start = dateTime_UNow;
240 this->UpdateEnd(); // Keep Duration constant and update End for changed Start.
241 }
242}

References m_DateTime_Start, m_pDatePickerCtrl_Start, m_pTimeTextCtrl_Start, NumericTextCtrl::SetValue(), UpdateEnd(), and wxDateTime_to_AudacityTime().

Referenced by OnDatePicker_Start(), and RunWaitDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnTimeText_Duration()

void TimerRecordDialog::OnTimeText_Duration ( wxCommandEvent &  event)
private

Definition at line 328 of file TimerRecordDialog.cpp.

329{
330 double dTime = m_pTimeTextCtrl_Duration->GetValue();
331 long hr = (long)(dTime / 3600.0);
332 long min = (long)((dTime - (hr * 3600.0)) / 60.0);
333 long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
334 m_TimeSpan_Duration = wxTimeSpan(hr, min, sec); //v milliseconds?
335
336 this->UpdateEnd(); // Keep Start constant and update End for changed Duration.
337}

References NumericConverter::GetValue(), m_pTimeTextCtrl_Duration, m_TimeSpan_Duration, min(), and UpdateEnd().

Here is the call graph for this function:

◆ OnTimeText_End()

void TimerRecordDialog::OnTimeText_End ( wxCommandEvent &  event)
private

Definition at line 308 of file TimerRecordDialog.cpp.

309{
310 //v NumericTextCtrl doesn't implement upper ranges, i.e.,
311 // if I tell it "024 h 060 m 060 s", then
312 // user increments the hours past 23, it rolls over to 0
313 // (although if you increment below 0, it stays at 0).
314 // So instead, set the max to 99 and just catch hours > 24 and fix the ctrls.
315 double dTime = m_pTimeTextCtrl_End->GetValue();
316 long days = (long)(dTime / (24.0 * 3600.0));
317 if (days > 0) {
318 dTime -= (double)days * 24.0 * 3600.0;
319 m_DateTime_End += wxTimeSpan::Days(days);
322 }
323
324 wxDateEvent dummyDateEvent;
325 this->OnDatePicker_End(dummyDateEvent);
326}
void OnDatePicker_End(wxDateEvent &event)

References NumericConverter::GetValue(), m_DateTime_End, m_pDatePickerCtrl_End, m_pTimeTextCtrl_End, OnDatePicker_End(), and NumericTextCtrl::SetValue().

Here is the call graph for this function:

◆ OnTimeText_Start()

void TimerRecordDialog::OnTimeText_Start ( wxCommandEvent &  event)
private

Definition at line 266 of file TimerRecordDialog.cpp.

267{
268 //v NumericTextCtrl doesn't implement upper ranges, i.e.,
269 // if I tell it "024 h 060 m 060 s", then
270 // user increments the hours past 23, it rolls over to 0
271 // (although if you increment below 0, it stays at 0).
272 // So instead, set the max to 99 and just catch hours > 24 and fix the ctrls.
273 double dTime = m_pTimeTextCtrl_Start->GetValue();
274 long days = (long)(dTime / (24.0 * 3600.0));
275 if (days > 0) {
276 dTime -= (double)days * 24.0 * 3600.0;
277 m_DateTime_Start += wxTimeSpan::Days(days);
280 }
281
282 wxDateEvent dummyDateEvent;
283 this->OnDatePicker_Start(dummyDateEvent);
284}
void OnDatePicker_Start(wxDateEvent &event)

References NumericConverter::GetValue(), m_DateTime_Start, m_pDatePickerCtrl_Start, m_pTimeTextCtrl_Start, OnDatePicker_Start(), and NumericTextCtrl::SetValue().

Here is the call graph for this function:

◆ PopulateOrExchange()

void TimerRecordDialog::PopulateOrExchange ( ShuttleGui S)
private

Definition at line 817 of file TimerRecordDialog.cpp.

818{
819 bool bAutoSave = gPrefs->ReadBool("/TimerRecord/AutoSave", false);
820 bool bAutoExport = gPrefs->ReadBool("/TimerRecord/AutoExport", false);
821 int iPostTimerRecordAction = gPrefs->ReadLong("/TimerRecord/PostAction", 0);
822
823 S.SetBorder(5);
825 /* i18n-hint a format string for hours, minutes, and seconds */
826 auto strFormat = XO("099 h 060 m 060 s");
827 /* i18n-hint a format string for days, hours, minutes, and seconds */
828 auto strFormat1 = XO("099 days 024 h 060 m 060 s");
829
830 S.StartMultiColumn(2, wxCENTER);
831 {
832 S.StartVerticalLay(true);
833 {
834 /* i18n-hint: This string is used to configure the controls for times when the recording is
835 * started and stopped. As such it is important that only the alphabetic parts of the string
836 * are translated, with the numbers left exactly as they are.
837 * The 'h' indicates the first number displayed is hours, the 'm' indicates the second number
838 * displayed is minutes, and the 's' indicates that the third number displayed is seconds.
839 */
840 S.StartStatic(XO("Start Date and Time"), true);
841 {
843 safenew wxDatePickerCtrl(S.GetParent(), // wxWindow *parent,
844 ID_DATEPICKER_START, // wxWindowID id,
845 m_DateTime_Start); // const wxDateTime& dt = wxDefaultDateTime,
846 // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
847 m_pDatePickerCtrl_Start->SetRange(wxDateTime::Today(), wxInvalidDateTime); // No backdating.
848#if wxUSE_ACCESSIBILITY
849 m_pDatePickerCtrl_Start->SetAccessible( safenew DatePickerCtrlAx(m_pDatePickerCtrl_Start));
850#endif
851 S.Name(XO("Start Date"))
852 .AddWindow(m_pDatePickerCtrl_Start);
853
856 {}, 0,
857 Options{}
858 .MenuEnabled(false)
859 .CustomFormat(strFormat)
861 S.Name(XO("Start Time"))
862 .AddWindow(m_pTimeTextCtrl_Start);
863 }
864 S.EndStatic();
865
866 S.StartStatic(XO("End Date and Time"), true);
867 {
869 safenew wxDatePickerCtrl(S.GetParent(), // wxWindow *parent,
870 ID_DATEPICKER_END, // wxWindowID id,
871 m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime,
872 // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
873 // long style = wxDP_DEFAULT | wxDP_SHOWCENTURY,
874 // const wxValidator& validator = wxDefaultValidator,
875 // const wxString& name = "datectrl")
876 m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
877#if wxUSE_ACCESSIBILITY
878 m_pDatePickerCtrl_End->SetAccessible( safenew DatePickerCtrlAx(m_pDatePickerCtrl_End));
879#endif
880 S.Name(XO("End Date"))
881 .AddWindow(m_pDatePickerCtrl_End);
882
885 {}, 0,
886 Options{}
887 .MenuEnabled(false)
888 .CustomFormat(strFormat)
890 S.Name(XO("End Time"))
891 .AddWindow(m_pTimeTextCtrl_End);
892 }
893 S.EndStatic();
894
895 S.StartStatic(XO("Duration"), true);
896 {
899 {}, 0,
900 Options{}
901 .MenuEnabled(false)
902 .CustomFormat(strFormat1)
903 .Value(true, m_TimeSpan_Duration.GetSeconds().ToDouble()));
904 /* i18n-hint: This string is used to configure the controls which shows the recording
905 * duration. As such it is important that only the alphabetic parts of the string
906 * are translated, with the numbers left exactly as they are.
907 * The string 'days' indicates that the first number in the control will be the number of days,
908 * then the 'h' indicates the second number displayed is hours, the 'm' indicates the third
909 * number displayed is minutes, and the 's' indicates that the fourth number displayed is
910 * seconds.
911 */
912 S.Name(XO("Duration"))
913 .AddWindow(m_pTimeTextCtrl_Duration);
914 }
915 S.EndStatic();
916 }
917 S.EndVerticalLay();
918
919 S.StartVerticalLay(true);
920 {
921 S.StartStatic(XO("Automatic Save"), true);
922 {
923 // If checked, the project will be saved when the recording is completed
924 m_pTimerAutoSaveCheckBoxCtrl = S.Id(ID_AUTOSAVE_CHECKBOX).AddCheckBox(XXO("Enable &Automatic Save?"),
925 bAutoSave);
926 S.StartMultiColumn(3, wxEXPAND);
927 {
928 TranslatableString sInitialValue;
929 auto sSaveValue = ProjectFileIO::Get(mProject).GetFileName();
930 if (!sSaveValue.empty()) {
931 m_fnAutoSaveFile.Assign(sSaveValue);
932 sInitialValue = XO("Current Project");
933 }
934 S.AddPrompt(XXO("Save Project As:"));
936 S.GetParent(), ID_AUTOSAVEPATH_TEXT,
937 XO("Save Project As:"), sInitialValue);
939 S.AddWindow(m_pTimerSavePathTextCtrl);
940 m_pTimerSavePathButtonCtrl = S.Id(ID_AUTOSAVEPATH_BUTTON).AddButton(XXO("Select..."));
941 }
942 S.EndMultiColumn();
943 }
944 S.EndStatic();
945
946 S.StartStatic(XO("Automatic Export"), true);
947 {
948 m_pTimerAutoExportCheckBoxCtrl = S.Id(ID_AUTOEXPORT_CHECKBOX).AddCheckBox(XXO("Enable Automatic &Export?"), bAutoExport);
949 S.StartMultiColumn(3, wxEXPAND);
950 {
951 S.AddPrompt(XXO("Export Project As:"));
953 S.GetParent(), ID_AUTOEXPORTPATH_TEXT,
954 XO("Export Project As:"), {});
956 m_pTimerExportPathTextCtrl->SetValue(m_fnAutoExportFile.GetFullPath());
957 S.AddWindow(m_pTimerExportPathTextCtrl);
958 m_pTimerExportPathButtonCtrl = S.Id(ID_AUTOEXPORTPATH_BUTTON).AddButton(XXO("Select..."));
959 }
960 S.EndMultiColumn();
961 }
962 S.EndStatic();
963
964 S.StartStatic(XO("Options"), true);
965 {
966
967 S.StartMultiColumn(1, wxEXPAND);
968 {
969 S.SetStretchyCol( 0 );
970 m_pTimerAfterCompleteChoiceCtrl = S.AddChoice(XXO("After Recording completes:"),
971 {
972 XO("Do nothing") ,
973 XO("Exit Audacity") ,
974 #ifdef __WINDOWS__
975 XO("Restart system") ,
976 XO("Shutdown system") ,
977 #endif
978 },
979 iPostTimerRecordAction
980 );
981 }
982 S.EndMultiColumn();
983 }
984 S.EndStatic();
985
986 }
987 S.EndVerticalLay();
988 }
989 S.EndMultiColumn();
990
991 // MY: Added the help button here
992 S.AddStandardButtons(eOkButton | eCancelButton | eHelpButton);
993
994 Layout();
995 Fit();
996 SetMinSize(GetSize());
997 Center();
998
1001}
XXO("&Cut/Copy/Paste Toolbar")
const NumericConverterType & NumericConverterType_TIME()
@ eOkButton
Definition: ShuttleGui.h:609
@ eCancelButton
Definition: ShuttleGui.h:610
@ eHelpButton
Definition: ShuttleGui.h:613
@ ID_AUTOEXPORTPATH_BUTTON
@ ID_AUTOSAVEPATH_TEXT
@ ID_DATEPICKER_START
@ ID_AUTOSAVEPATH_BUTTON
@ ID_AUTOSAVE_CHECKBOX
@ ID_AUTOEXPORTPATH_TEXT
@ ID_TIMETEXT_DURATION
@ ID_TIMETEXT_END
@ ID_DATEPICKER_END
@ ID_TIMETEXT_START
@ ID_AUTOEXPORT_CHECKBOX
static FormatterContext EmptyContext()
const FilePath & GetFileName() const
wxTextCtrlWrapper * NewPathControl(wxWindow *wParent, const int iID, const TranslatableString &sCaption, const TranslatableString &sValue)
Holds a msgid for the translation catalog; may also bind format arguments.
long ReadLong(const wxString &key, long defaultValue) const
bool ReadBool(const wxString &key, bool defaultValue) const
void SetReadOnly(bool readonly=true)

References CONTROL_GROUP_EXPORT, CONTROL_GROUP_SAVE, eCancelButton, eHelpButton, FormatterContext::EmptyContext(), EnableDisableAutoControls(), eOkButton, ProjectFileIO::Get(), ProjectFileIO::GetFileName(), gPrefs, ID_AUTOEXPORT_CHECKBOX, ID_AUTOEXPORTPATH_BUTTON, ID_AUTOEXPORTPATH_TEXT, ID_AUTOSAVE_CHECKBOX, ID_AUTOSAVEPATH_BUTTON, ID_AUTOSAVEPATH_TEXT, ID_DATEPICKER_END, ID_DATEPICKER_START, ID_TIMETEXT_DURATION, ID_TIMETEXT_END, ID_TIMETEXT_START, m_DateTime_End, m_DateTime_Start, m_fnAutoExportFile, m_fnAutoSaveFile, m_pDatePickerCtrl_End, m_pDatePickerCtrl_Start, m_pTimerAfterCompleteChoiceCtrl, m_pTimerAutoExportCheckBoxCtrl, m_pTimerAutoSaveCheckBoxCtrl, m_pTimerExportPathButtonCtrl, m_pTimerExportPathTextCtrl, m_pTimerSavePathButtonCtrl, m_pTimerSavePathTextCtrl, m_pTimeTextCtrl_Duration, m_pTimeTextCtrl_End, m_pTimeTextCtrl_Start, m_TimeSpan_Duration, mProject, NewPathControl(), NumericConverterType_TIME(), audacity::BasicSettings::ReadBool(), audacity::BasicSettings::ReadLong(), S, safenew, wxTextCtrlWrapper::SetReadOnly(), wxDateTime_to_AudacityTime(), XO(), and XXO().

Here is the call graph for this function:

◆ PreActionDelay()

ProgressResult TimerRecordDialog::PreActionDelay ( int  iActionIndex,
TimerRecordCompletedActions  eCompletedActions 
)
private

Definition at line 1121 of file TimerRecordDialog.cpp.

1122{
1124 ->GetString(iActionIndex) );
1125
1126 /* i18n-hint: %s is one of "Do nothing", "Exit Audacity", "Restart system",
1127 or "Shutdown system", and
1128 "in" means after a duration of time, shown below this string */
1129 auto sCountdownLabel = XO("%s in:").Format( sAction );
1130
1131 // Two column layout.
1133 {
1134 XO("Timer Recording completed.") ,
1135 {} ,
1136 XO("Recording Saved:") ,
1137 XO("Recording Exported:") ,
1138 XO("Action after Timer Recording:") ,
1139 },
1140 {
1141 {} ,
1142 {} ,
1143 ((eCompletedActions & TR_ACTION_SAVED) ? XO("Yes") : XO("No")) ,
1144 ((eCompletedActions & TR_ACTION_EXPORTED) ? XO("Yes") : XO("No")) ,
1145 sAction ,
1146 },
1147 };
1148
1149
1150 wxDateTime dtNow = wxDateTime::UNow();
1151 wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
1152 wxDateTime dtActionTime = dtNow.Add(tsWait);
1153
1154 TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
1155 XO("Audacity Timer Record - Waiting"),
1156 columns,
1158 sCountdownLabel);
1159
1160 auto iUpdateResult = ProgressResult::Success;
1161 bool bIsTime = false;
1162 while (iUpdateResult == ProgressResult::Success && !bIsTime)
1163 {
1164 iUpdateResult = dlgAction.UpdateProgress();
1165 using namespace std::chrono;
1166 std::this_thread::sleep_for(kTimerInterval);
1167 bIsTime = (dtActionTime <= wxDateTime::UNow());
1168 }
1169 return iUpdateResult;
1170}
@ pdlgHideStopButton
@ pdlgHideElapsedTime
constexpr auto kTimerInterval
std::vector< MessageColumn > MessageTable

References kTimerInterval, m_pTimerAfterCompleteChoiceCtrl, pdlgHideElapsedTime, pdlgHideStopButton, BasicUI::Success, TR_ACTION_EXPORTED, TR_ACTION_SAVED, TimerProgressDialog::UpdateProgress(), Verbatim(), and XO().

Referenced by ExecutePostRecordActions().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RunWaitDialog()

int TimerRecordDialog::RunWaitDialog ( )

Runs the wait for start dialog. Returns false if the user clicks stop.

Runs the wait for start dialog. Returns -1 if the user clicks stop while we are recording or if the post recording actions fail.

Definition at line 522 of file TimerRecordDialog.cpp.

523{
524 auto updateResult = ProgressResult::Success;
525
526 const auto gAudioIO = AudioIO::Get();
527 gAudioIO->DelayActions(true);
528 {
529 auto cleanup = finally([gAudioIO]{ gAudioIO->DelayActions(false); });
530
531 if (m_DateTime_Start > wxDateTime::UNow())
532 updateResult = this->WaitForStart();
533
534 if (updateResult != ProgressResult::Success) {
535 // Don't proceed, but don't treat it as canceled recording. User just canceled waiting.
537 } else {
538 // Record for specified time.
540 bool bIsRecording = true;
541
542 auto sPostAction = Verbatim(
543 m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() );
544
545 // Two column layout.
547 {
548 XO("Recording start:") ,
549 XO("Duration:") ,
550 XO("Recording end:") ,
551 {} ,
552 XO("Automatic Save enabled:") ,
553 XO("Automatic Export enabled:") ,
554 XO("Action after Timer Recording:") ,
555 },
556 {
558 Verbatim( m_TimeSpan_Duration.Format() ),
560 {} ,
561 (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) ,
562 (m_bAutoExportEnabled ? XO("Yes") : XO("No")) ,
563 sPostAction ,
564 }
565 };
566
568 progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(),
569 XO("Audacity Timer Record Progress"),
570 columns,
572
573 // Make sure that start and end time are updated, so we always get the full
574 // duration, even if there's some delay getting here.
575 wxTimerEvent dummyTimerEvent;
576 this->OnTimer(dummyTimerEvent);
577
578 // Loop for progress display during recording.
579 while (bIsRecording && (updateResult == ProgressResult::Success)) {
580 updateResult = progress.UpdateProgress();
581 using namespace std::chrono;
582 std::this_thread::sleep_for(kTimerInterval);
583 bIsRecording = (wxDateTime::UNow() <= m_DateTime_End); // Call UNow() again for extra accuracy...
584 }
585 }
586 }
587
588 // Must do this AFTER the timer project dialog has been deleted to ensure the application
589 // responds to the AUDIOIO events...see not about bug #334 in the ProgressDialog constructor.
591
592 // Let the caller handle cancellation or failure from recording progress.
593 if (updateResult == ProgressResult::Cancelled || updateResult == ProgressResult::Failed)
595
596 return ExecutePostRecordActions((updateResult == ProgressResult::Stopped));
597}
@ pdlgConfirmStopCancel
@ pdlgHideCancelButton
@ POST_TIMER_RECORD_CANCEL
@ POST_TIMER_RECORD_CANCEL_WAIT
static AudioIO * Get()
Definition: AudioIO.cpp:126
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
void OnRecord(bool altAppearance)
TranslatableString GetDisplayDate(wxDateTime &dt)
int ExecutePostRecordActions(bool bWasStopped)
ProgressResult WaitForStart()

References BasicUI::Cancelled, ExecutePostRecordActions(), BasicUI::Failed, AudioIO::Get(), ProjectAudioManager::Get(), GetDisplayDate(), kTimerInterval, m_bAutoExportEnabled, m_bAutoSaveEnabled, m_DateTime_End, m_DateTime_Start, m_pTimerAfterCompleteChoiceCtrl, m_TimeSpan_Duration, mProject, ProjectAudioManager::OnRecord(), OnTimer(), pdlgConfirmStopCancel, pdlgHideCancelButton, POST_TIMER_RECORD_CANCEL, POST_TIMER_RECORD_CANCEL_WAIT, ProjectAudioManager::Stop(), BasicUI::Stopped, BasicUI::Success, TimerProgressDialog::UpdateProgress(), Verbatim(), WaitForStart(), and XO().

Referenced by anonymous_namespace{TimerRecordDialog.cpp}::OnTimerRecord().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TransferDataFromWindow()

bool TimerRecordDialog::TransferDataFromWindow ( )
overrideprivate

Definition at line 1003 of file TimerRecordDialog.cpp.

1004{
1005 double dTime;
1006 long hr;
1007 long min;
1008 long sec;
1009
1012 hr = (long)(dTime / 3600.0);
1013 min = (long)((dTime - (hr * 3600.0)) / 60.0);
1014 sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
1015 m_DateTime_Start.SetHour(hr);
1016 m_DateTime_Start.SetMinute(min);
1017 m_DateTime_Start.SetSecond(sec);
1018
1020 dTime = m_pTimeTextCtrl_End->GetValue();
1021 hr = (long)(dTime / 3600.0);
1022 min = (long)((dTime - (hr * 3600.0)) / 60.0);
1023 sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
1024 m_DateTime_End.SetHour(hr);
1025 m_DateTime_End.SetMinute(min);
1026 m_DateTime_End.SetSecond(sec);
1027
1029
1030 // Pull the settings from the auto save/export controls and write to the pref file
1033
1034 // MY: Obtain the index from the choice control so we can save to the prefs file
1035 int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
1036
1037 // Save the options back to the prefs file
1038 gPrefs->Write("/TimerRecord/AutoSave", m_bAutoSaveEnabled);
1039 gPrefs->Write("/TimerRecord/AutoExport", m_bAutoExportEnabled);
1040 gPrefs->Write("/TimerRecord/PostAction", iPostRecordAction);
1041
1042 return true;
1043}

References NumericConverter::GetValue(), gPrefs, m_bAutoExportEnabled, m_bAutoSaveEnabled, m_DateTime_End, m_DateTime_Start, m_pDatePickerCtrl_End, m_pDatePickerCtrl_Start, m_pTimerAfterCompleteChoiceCtrl, m_pTimerAutoExportCheckBoxCtrl, m_pTimerAutoSaveCheckBoxCtrl, m_pTimeTextCtrl_End, m_pTimeTextCtrl_Start, m_TimeSpan_Duration, min(), and audacity::BasicSettings::Write().

Referenced by OnOK().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateDuration()

void TimerRecordDialog::UpdateDuration ( )
private

Definition at line 1046 of file TimerRecordDialog.cpp.

References m_DateTime_End, m_DateTime_Start, m_pTimeTextCtrl_Duration, m_TimeSpan_Duration, and NumericTextCtrl::SetValue().

Referenced by OnDatePicker_End().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateEnd()

void TimerRecordDialog::UpdateEnd ( )
private

Definition at line 1053 of file TimerRecordDialog.cpp.

1054{
1055 //v Use remaining disk -> record time calcs from AudacityProject::OnTimer to set range?
1057 //wxLogDebug( "Time start %s end %s",
1058 // m_DateTime_Start.FormatISOCombined(' '),
1059 // m_DateTime_End.FormatISOCombined(' ') );
1060
1061 // Disable the range limitation (to fix Bug 1749 and 1978)
1062 // Otherwise SetVallue asserts when going back in time.
1063 m_pDatePickerCtrl_End->SetRange(wxInvalidDateTime, wxInvalidDateTime);
1065 // Re-enable range limitation to constrain user input.
1066 m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
1067 m_pDatePickerCtrl_End->Refresh();
1069}

References m_DateTime_End, m_DateTime_Start, m_pDatePickerCtrl_End, m_pTimeTextCtrl_End, m_TimeSpan_Duration, NumericTextCtrl::SetValue(), and wxDateTime_to_AudacityTime().

Referenced by OnDatePicker_Start(), OnTimer(), and OnTimeText_Duration().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateTextBoxControls()

void TimerRecordDialog::UpdateTextBoxControls ( )
private

Definition at line 509 of file TimerRecordDialog.cpp.

509 {
510 // Will update the text box controls
511 m_pTimerSavePathTextCtrl->SetValue(m_fnAutoSaveFile.GetFullPath());
512 m_pTimerExportPathTextCtrl->SetValue(m_fnAutoExportFile.GetFullPath());
513
514 // MY: Ensure we still display "Current Project" if this has already been saved
516 m_pTimerSavePathTextCtrl->SetValue(_("Current Project"));
517 }
518}

References _, m_bProjectAlreadySaved, m_fnAutoExportFile, m_fnAutoSaveFile, m_pTimerExportPathTextCtrl, and m_pTimerSavePathTextCtrl.

Referenced by OnAutoExportPathButton_Click(), and OnAutoSavePathButton_Click().

Here is the caller graph for this function:

◆ WaitForStart()

ProgressResult TimerRecordDialog::WaitForStart ( )
private

Definition at line 1071 of file TimerRecordDialog.cpp.

1072{
1073 // MY: The Waiting For Start dialog now shows what actions will occur after recording has completed
1074 auto sPostAction = Verbatim(
1075 m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() );
1076
1077 // Two column layout.
1079 {
1080 XO("Waiting to start recording at:") ,
1081 XO("Recording duration:") ,
1082 XO("Scheduled to stop at:") ,
1083 {} ,
1084 XO("Automatic Save enabled:") ,
1085 XO("Automatic Export enabled:") ,
1086 XO("Action after Timer Recording:") ,
1087 },
1088 {
1090 Verbatim( m_TimeSpan_Duration.Format() ),
1092 {} ,
1093 (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) ,
1094 (m_bAutoExportEnabled ? XO("Yes") : XO("No")) ,
1095 sPostAction ,
1096 },
1097 };
1098
1099 wxDateTime startWait_DateTime = wxDateTime::UNow();
1100 wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime;
1101 TimerProgressDialog progress(waitDuration.GetMilliseconds().GetValue(),
1102 XO("Audacity Timer Record - Waiting for Start"),
1103 columns,
1105 /* i18n-hint: "in" means after a duration of time,
1106 which is shown below this string */
1107 XO("Recording will commence in:"));
1108
1109 auto updateResult = ProgressResult::Success;
1110 bool bIsRecording = false;
1111 while (updateResult == ProgressResult::Success && !bIsRecording)
1112 {
1113 updateResult = progress.UpdateProgress();
1114 using namespace std::chrono;
1115 std::this_thread::sleep_for(kTimerInterval);
1116 bIsRecording = (m_DateTime_Start <= wxDateTime::UNow());
1117 }
1118 return updateResult;
1119}

References GetDisplayDate(), kTimerInterval, m_bAutoExportEnabled, m_bAutoSaveEnabled, m_DateTime_End, m_DateTime_Start, m_pTimerAfterCompleteChoiceCtrl, m_TimeSpan_Duration, pdlgConfirmStopCancel, pdlgHideElapsedTime, pdlgHideStopButton, BasicUI::Success, TimerProgressDialog::UpdateProgress(), Verbatim(), and XO().

Referenced by RunWaitDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_AutoExportParameters

ExportProcessor::Parameters TimerRecordDialog::m_AutoExportParameters
private

Definition at line 149 of file TimerRecordDialog.h.

Referenced by ExecutePostRecordActions(), and OnAutoExportPathButton_Click().

◆ m_bAutoExportEnabled

bool TimerRecordDialog::m_bAutoExportEnabled
private

◆ m_bAutoSaveEnabled

bool TimerRecordDialog::m_bAutoSaveEnabled
private

◆ m_bProjectAlreadySaved

bool TimerRecordDialog::m_bProjectAlreadySaved
private

◆ m_bProjectCleanupRequired

bool TimerRecordDialog::m_bProjectCleanupRequired
private

Definition at line 139 of file TimerRecordDialog.h.

◆ m_DateTime_End

wxDateTime TimerRecordDialog::m_DateTime_End
private

◆ m_DateTime_Start

wxDateTime TimerRecordDialog::m_DateTime_Start
private

◆ m_fnAutoExportFile

wxFileName TimerRecordDialog::m_fnAutoExportFile
private

◆ m_fnAutoSaveFile

wxFileName TimerRecordDialog::m_fnAutoSaveFile
private

◆ m_iAutoExportChannels

int TimerRecordDialog::m_iAutoExportChannels {0}
private

Definition at line 148 of file TimerRecordDialog.h.

Referenced by ExecutePostRecordActions(), and OnAutoExportPathButton_Click().

◆ m_iAutoExportSampleRate

int TimerRecordDialog::m_iAutoExportSampleRate {0}
private

Definition at line 147 of file TimerRecordDialog.h.

Referenced by ExecutePostRecordActions(), and OnAutoExportPathButton_Click().

◆ m_pDatePickerCtrl_End

wxDatePickerCtrl* TimerRecordDialog::m_pDatePickerCtrl_End
private

◆ m_pDatePickerCtrl_Start

wxDatePickerCtrl* TimerRecordDialog::m_pDatePickerCtrl_Start
private

◆ m_pTimerAfterCompleteChoiceCtrl

wxChoice* TimerRecordDialog::m_pTimerAfterCompleteChoiceCtrl
private

◆ m_pTimerAutoExportCheckBoxCtrl

wxCheckBox* TimerRecordDialog::m_pTimerAutoExportCheckBoxCtrl
private

◆ m_pTimerAutoSaveCheckBoxCtrl

wxCheckBox* TimerRecordDialog::m_pTimerAutoSaveCheckBoxCtrl
private

◆ m_pTimerExportPathButtonCtrl

wxButton* TimerRecordDialog::m_pTimerExportPathButtonCtrl
private

Definition at line 133 of file TimerRecordDialog.h.

Referenced by EnableDisableAutoControls(), and PopulateOrExchange().

◆ m_pTimerExportPathTextCtrl

wxTextCtrlWrapper* TimerRecordDialog::m_pTimerExportPathTextCtrl
private

◆ m_pTimerSavePathButtonCtrl

wxButton* TimerRecordDialog::m_pTimerSavePathButtonCtrl
private

Definition at line 130 of file TimerRecordDialog.h.

Referenced by EnableDisableAutoControls(), and PopulateOrExchange().

◆ m_pTimerSavePathTextCtrl

wxTextCtrlWrapper* TimerRecordDialog::m_pTimerSavePathTextCtrl
private

◆ m_pTimeTextCtrl_Duration

NumericTextCtrl* TimerRecordDialog::m_pTimeTextCtrl_Duration
private

Definition at line 123 of file TimerRecordDialog.h.

Referenced by OnTimeText_Duration(), PopulateOrExchange(), and UpdateDuration().

◆ m_pTimeTextCtrl_End

NumericTextCtrl* TimerRecordDialog::m_pTimeTextCtrl_End
private

◆ m_pTimeTextCtrl_Start

NumericTextCtrl* TimerRecordDialog::m_pTimeTextCtrl_Start
private

◆ m_sAutoExportFormat

wxString TimerRecordDialog::m_sAutoExportFormat
private

Definition at line 146 of file TimerRecordDialog.h.

Referenced by ExecutePostRecordActions(), and OnAutoExportPathButton_Click().

◆ m_timer

wxTimer TimerRecordDialog::m_timer
private

Definition at line 125 of file TimerRecordDialog.h.

Referenced by OnOK().

◆ m_TimeSpan_Duration

wxTimeSpan TimerRecordDialog::m_TimeSpan_Duration
private

◆ mProject

AudacityProject& TimerRecordDialog::mProject
private

The documentation for this class was generated from the following files: