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
217
218 ShuttleGui S(this, eIsCreating);
219 this->PopulateOrExchange(S);
220
221 // Set initial focus to "1" of "01h" in Duration NumericTextCtrl,
222 // instead of OK button (default).
223 m_pTimeTextCtrl_Duration->SetFocus();
225
226 m_timer.SetOwner(this, TIMER_ID);
228}
wxT("CloseDown"))
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:205
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:630
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 489 of file TimerRecordDialog.cpp.

489 {
490
491 if (iControlGoup == CONTROL_GROUP_EXPORT) {
492 m_pTimerExportPathTextCtrl->Enable( bEnable );
493 m_pTimerExportPathButtonCtrl->Enable( bEnable);
494 } else if (iControlGoup == CONTROL_GROUP_SAVE) {
495 m_pTimerSavePathTextCtrl->Enable( bEnable);
496 m_pTimerSavePathButtonCtrl->Enable(bEnable );
497 }
498
499 // Enable or disable the Choice box - if there is no Save or Export then this will be disabled
500 if (m_pTimerAutoSaveCheckBoxCtrl->GetValue() || m_pTimerAutoExportCheckBoxCtrl->GetValue()) {
502 } else {
505 }
506}
@ 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 598 of file TimerRecordDialog.cpp.

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

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

808{
809 wxTextCtrlWrapper * pTextCtrl;
810 wxASSERT(wParent); // to justify safenew
811 pTextCtrl = safenew wxTextCtrlWrapper(wParent, iID, sValue.Translation());
812 pTextCtrl->SetName(sCaption.Translation());
813 return pTextCtrl;
814}
#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 401 of file TimerRecordDialog.cpp.

401 {
403}
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 377 of file TimerRecordDialog.cpp.

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

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 397 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 339 of file TimerRecordDialog.cpp.

340{
341 auto &projectFileIO = ProjectFileIO::Get(mProject);
342
343 wxString fName = SelectFile(FileNames::Operation::Export,
344 XO("Save Timer Recording As"),
345 m_fnAutoSaveFile.GetPath(),
346 m_fnAutoSaveFile.GetFullName(),
347 wxT("aup3"),
349 wxFD_SAVE | wxRESIZE_BORDER,
350 this);
351
352 if (fName.empty())
353 return;
354
355 // If project already exists then abort - we do not allow users to overwrite an existing project
356 // unless it is the current project.
357 if (wxFileExists(fName) && (projectFileIO.GetFileName() != fName)) {
359 nullptr,
360 XO("The selected file name could not be used\nfor Timer Recording because it \
361would overwrite another project.\nPlease try again and select an original name."),
362 XO("Error Saving Timer Recording Project"),
363 wxOK|wxICON_ERROR );
364 m.ShowModal();
365 return;
366 }
367
368 // Set this boolean to false so we now do a SaveAs at the end of the recording
369 // unless we're saving the current project.
370 m_bProjectAlreadySaved = projectFileIO.GetFileName() == fName? true : false;
371
372 m_fnAutoSaveFile = fName;
373 m_fnAutoSaveFile.SetExt(wxT("aup3"));
374 this->UpdateTextBoxControls();
375}
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 285 of file TimerRecordDialog.cpp.

286{
288 double dTime = m_pTimeTextCtrl_End->GetValue();
289 long hr = (long)(dTime / 3600.0);
290 long min = (long)((dTime - (hr * 3600.0)) / 60.0);
291 long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
292 m_DateTime_End.SetHour(hr);
293 m_DateTime_End.SetMinute(min);
294 m_DateTime_End.SetSecond(sec);
295
296 // DatePickerCtrls use SetRange to make sure End is never less than Start, but
297 // need to implement it for the TimeTextCtrls.
302 }
303
304 this->UpdateDuration(); // Keep Start constant and update Duration for changed End.
305}
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 243 of file TimerRecordDialog.cpp.

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

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

References HelpSystem::ShowHelp().

Here is the call graph for this function:

◆ OnOK()

void TimerRecordDialog::OnOK ( wxCommandEvent &  event)
private

Definition at line 410 of file TimerRecordDialog.cpp.

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

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

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 327 of file TimerRecordDialog.cpp.

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

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 307 of file TimerRecordDialog.cpp.

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

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

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

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

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

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

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 1045 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 1052 of file TimerRecordDialog.cpp.

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

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 508 of file TimerRecordDialog.cpp.

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

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 1070 of file TimerRecordDialog.cpp.

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

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: