Audacity  3.0.3
TimerRecordDialog.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  TimerRecordDialog.cpp
6 
7  Copyright 2006-2009 by Vaughan Johnson
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14 *******************************************************************//*******************************************************************/
20 
21 
22 #include "TimerRecordDialog.h"
23 
24 #include "FileNames.h"
25 
26 #include <wx/setup.h> // for wxUSE_* macros
27 
28 #include <wx/wxcrtvararg.h>
29 #include <wx/button.h>
30 #include <wx/calctrl.h>
31 #include <wx/checkbox.h>
32 #include <wx/choice.h>
33 #include <wx/defs.h>
34 #include <wx/dir.h>
35 #include <wx/datectrl.h>
36 #include <wx/datetime.h>
37 #include <wx/intl.h>
38 #include <wx/sizer.h>
39 #include <wx/string.h>
40 #include <wx/timer.h>
41 #include <wx/dynlib.h> //<! For windows.h
42 
43 #include "AudioIO.h"
44 #include "ShuttleGui.h"
45 #include "ProjectAudioManager.h"
46 #include "ProjectFileIO.h"
47 #include "ProjectFileManager.h"
48 #include "ProjectManager.h"
49 #include "Prefs.h"
50 #include "Track.h"
52 #include "widgets/HelpSystem.h"
54 #include "widgets/ProgressDialog.h"
56 
57 #if wxUSE_ACCESSIBILITY
59 #endif
60 
61 #define TIMER_ID 7000
62 
63 enum { // control IDs
75 };
76 
77 enum {
80 };
81 
82 // The slow timer interval is used to update the start and end times, which only show
83 // time to the nearest second. So we only need an update once a second.
84 const int kSlowTimerInterval = 1000; // ms
85 
86 // This timer interval is used in some busy-wait loops and is much shorter.
87 const int kTimerInterval = 50; // ms
88 
89 static double wxDateTime_to_AudacityTime(wxDateTime& dateTime)
90 {
91  return (dateTime.GetHour() * 3600.0) + (dateTime.GetMinute() * 60.0) + dateTime.GetSecond();
92 };
93 
94 
95 // The purpose of the DatePickerCtrlAx class is to make to wxDatePickerCtrl more accessible for
96 // the NVDA screen reader.
97 // By default the msaa state of wxDatePickerCtrl is always normal (0x0), and this causes nvda not
98 // to read the control when the user tabs to it. This class
99 // modifies the state to be focusable + focused (when it's the focus).
100 // Note that even with this class NVDA still doesn't read the NEW selected part of the control when left/right
101 // arrow keys are used.
102 
103 #if wxUSE_ACCESSIBILITY
104 
105 class DatePickerCtrlAx final : public WindowAccessible
106 {
107 public:
108  DatePickerCtrlAx(wxDatePickerCtrl * ctrl) : WindowAccessible(ctrl), mCtrl(ctrl) {};
109 
110  virtual ~ DatePickerCtrlAx() {};
111 
112  // Returns a state constant.
113  wxAccStatus GetState(int childId, long *state) override;
114 
115 private:
116  wxDatePickerCtrl *mCtrl;
117 };
118 
119 // Returns a state constant.
120 wxAccStatus DatePickerCtrlAx::GetState(int WXUNUSED(childId), long *state)
121 {
122  *state = wxACC_STATE_SYSTEM_FOCUSABLE;
123  *state |= (mCtrl == wxWindow::FindFocus() ? wxACC_STATE_SYSTEM_FOCUSED : 0);
124 
125  return wxACC_OK;
126 }
127 
128 #endif // wxUSE_ACCESSIBILITY
129 
130 
131 BEGIN_EVENT_TABLE(TimerRecordDialog, wxDialogWrapper)
134 
137 
139 
142 
144 
147 
150 
152 
154  wxWindow* parent, AudacityProject &project, bool bAlreadySaved)
155 : wxDialogWrapper(parent, -1, XO("Audacity Timer Record"), wxDefaultPosition,
156  wxDefaultSize, wxCAPTION)
157 , mProject{ project }
158 {
159  SetName();
160 
161  m_DateTime_Start = wxDateTime::UNow();
162  long seconds; // default duration is 1 hour = 3600 seconds
163  gPrefs->Read(wxT("/TimerRecord/LastDuration"), &seconds, 3600);
164  m_TimeSpan_Duration = wxTimeSpan::Seconds(seconds);
165  m_DateTime_End = m_DateTime_Start + m_TimeSpan_Duration;
166 
167  m_pDatePickerCtrl_Start = NULL;
168  m_pTimeTextCtrl_Start = NULL;
169 
170  m_pDatePickerCtrl_End = NULL;
171  m_pTimeTextCtrl_End = NULL;
172 
173  m_pTimeTextCtrl_Duration = NULL;
174 
175  // Do we allow the user to change the Automatic Save file?
176  m_bProjectAlreadySaved = bAlreadySaved;
177 
178  ShuttleGui S(this, eIsCreating);
179  this->PopulateOrExchange(S);
180 
181  // Set initial focus to "1" of "01h" in Duration NumericTextCtrl,
182  // instead of OK button (default).
183  m_pTimeTextCtrl_Duration->SetFocus();
184  m_pTimeTextCtrl_Duration->SetFieldFocus(3);
185 
186  m_timer.SetOwner(this, TIMER_ID);
187  m_timer.Start(kSlowTimerInterval);
188 }
189 
191 {
192 }
193 
194 void TimerRecordDialog::OnTimer(wxTimerEvent& WXUNUSED(event))
195 {
196  wxDateTime dateTime_UNow = wxDateTime::UNow();
197  if (m_DateTime_Start < dateTime_UNow) {
198  m_DateTime_Start = dateTime_UNow;
201  this->UpdateEnd(); // Keep Duration constant and update End for changed Start.
202  }
203 }
204 
205 void TimerRecordDialog::OnDatePicker_Start(wxDateEvent& WXUNUSED(event))
206 {
208  double dTime = m_pTimeTextCtrl_Start->GetValue();
209  long hr = (long)(dTime / 3600.0);
210  long min = (long)((dTime - (hr * 3600.0)) / 60.0);
211  long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
212  m_DateTime_Start.SetHour(hr);
213  m_DateTime_Start.SetMinute(min);
214  m_DateTime_Start.SetSecond(sec);
215 
216  // User might have had the dialog up for a while, or
217  // had a future day, set hour of day less than now's, then changed day to today.
218  wxTimerEvent dummyTimerEvent;
219  this->OnTimer(dummyTimerEvent);
220 
221  // Always update End for changed Start, keeping Duration constant.
222  // Note that OnTimer sometimes calls UpdateEnd, so sometimes this is redundant,
223  // but OnTimer doesn't need to always call UpdateEnd, but we must here.
224  this->UpdateEnd();
225 }
226 
227 void TimerRecordDialog::OnTimeText_Start(wxCommandEvent& WXUNUSED(event))
228 {
229  //v NumericTextCtrl doesn't implement upper ranges, i.e.,
230  // if I tell it "024 h 060 m 060 s", then
231  // user increments the hours past 23, it rolls over to 0
232  // (although if you increment below 0, it stays at 0).
233  // So instead, set the max to 99 and just catch hours > 24 and fix the ctrls.
234  double dTime = m_pTimeTextCtrl_Start->GetValue();
235  long days = (long)(dTime / (24.0 * 3600.0));
236  if (days > 0) {
237  dTime -= (double)days * 24.0 * 3600.0;
238  m_DateTime_Start += wxTimeSpan::Days(days);
241  }
242 
243  wxDateEvent dummyDateEvent;
244  this->OnDatePicker_Start(dummyDateEvent);
245 }
246 
247 void TimerRecordDialog::OnDatePicker_End(wxDateEvent& WXUNUSED(event))
248 {
250  double dTime = m_pTimeTextCtrl_End->GetValue();
251  long hr = (long)(dTime / 3600.0);
252  long min = (long)((dTime - (hr * 3600.0)) / 60.0);
253  long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
254  m_DateTime_End.SetHour(hr);
255  m_DateTime_End.SetMinute(min);
256  m_DateTime_End.SetSecond(sec);
257 
258  // DatePickerCtrls use SetRange to make sure End is never less than Start, but
259  // need to implement it for the TimeTextCtrls.
264  }
265 
266  this->UpdateDuration(); // Keep Start constant and update Duration for changed End.
267 }
268 
269 void TimerRecordDialog::OnTimeText_End(wxCommandEvent& WXUNUSED(event))
270 {
271  //v NumericTextCtrl doesn't implement upper ranges, i.e.,
272  // if I tell it "024 h 060 m 060 s", then
273  // user increments the hours past 23, it rolls over to 0
274  // (although if you increment below 0, it stays at 0).
275  // So instead, set the max to 99 and just catch hours > 24 and fix the ctrls.
276  double dTime = m_pTimeTextCtrl_End->GetValue();
277  long days = (long)(dTime / (24.0 * 3600.0));
278  if (days > 0) {
279  dTime -= (double)days * 24.0 * 3600.0;
280  m_DateTime_End += wxTimeSpan::Days(days);
283  }
284 
285  wxDateEvent dummyDateEvent;
286  this->OnDatePicker_End(dummyDateEvent);
287 }
288 
289 void TimerRecordDialog::OnTimeText_Duration(wxCommandEvent& WXUNUSED(event))
290 {
291  double dTime = m_pTimeTextCtrl_Duration->GetValue();
292  long hr = (long)(dTime / 3600.0);
293  long min = (long)((dTime - (hr * 3600.0)) / 60.0);
294  long sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
295  m_TimeSpan_Duration = wxTimeSpan(hr, min, sec); //v milliseconds?
296 
297  this->UpdateEnd(); // Keep Start constant and update End for changed Duration.
298 }
299 
300 // New events for timer recording automation
301 void TimerRecordDialog::OnAutoSavePathButton_Click(wxCommandEvent& WXUNUSED(event))
302 {
303  auto &projectFileIO = ProjectFileIO::Get(mProject);
304 
305  wxString fName = FileNames::SelectFile(FileNames::Operation::Export,
306  XO("Save Timer Recording As"),
307  m_fnAutoSaveFile.GetPath(),
308  m_fnAutoSaveFile.GetFullName(),
309  wxT("aup3"),
311  wxFD_SAVE | wxRESIZE_BORDER,
312  this);
313 
314  if (fName.empty())
315  return;
316 
317  // If project already exists then abort - we do not allow users to overwrite an existing project
318  // unless it is the current project.
319  if (wxFileExists(fName) && (projectFileIO.GetFileName() != fName)) {
321  nullptr,
322  XO("The selected file name could not be used\nfor Timer Recording because it \
323 would overwrite another project.\nPlease try again and select an original name."),
324  XO("Error Saving Timer Recording Project"),
325  wxOK|wxICON_ERROR );
326  m.ShowModal();
327  return;
328  }
329 
330  // Set this boolean to false so we now do a SaveAs at the end of the recording
331  // unless we're saving the current project.
332  m_bProjectAlreadySaved = projectFileIO.GetFileName() == fName? true : false;
333 
334  m_fnAutoSaveFile = fName;
335  m_fnAutoSaveFile.SetExt(wxT("aup3"));
336  this->UpdateTextBoxControls();
337 }
338 
339 void TimerRecordDialog::OnAutoExportPathButton_Click(wxCommandEvent& WXUNUSED(event))
340 {
341  Exporter eExporter{ mProject };
342 
343  // Call the Exporter to set the options required
344  if (eExporter.SetAutoExportOptions()) {
345  // Populate the options so that we can destroy this instance of the Exporter
346  m_fnAutoExportFile = eExporter.GetAutoExportFileName();
347  m_iAutoExportFormat = eExporter.GetAutoExportFormat();
348  m_iAutoExportSubFormat = eExporter.GetAutoExportSubFormat();
349  m_iAutoExportFilterIndex = eExporter.GetAutoExportFilterIndex();
350 
351  // Update the text controls
352  this->UpdateTextBoxControls();
353  }
354 }
355 
356 void TimerRecordDialog::OnAutoSaveCheckBox_Change(wxCommandEvent& WXUNUSED(event)) {
358 }
359 
360 void TimerRecordDialog::OnAutoExportCheckBox_Change(wxCommandEvent& WXUNUSED(event)) {
362 }
363 
364 void TimerRecordDialog::OnHelpButtonClick(wxCommandEvent& WXUNUSED(event))
365 {
366  HelpSystem::ShowHelp(this, L"Timer_Record", true);
367 }
368 
369 void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event))
370 {
371  this->TransferDataFromWindow();
372  if (!m_TimeSpan_Duration.IsPositive())
373  {
375  XO("Duration is zero. Nothing will be recorded."),
376  XO("Error in Duration"),
377  wxICON_EXCLAMATION | wxOK);
378  return;
379  }
380 
381  // Validate that we have a Save and/or Export path setup if the appropriate check box is ticked
382  wxString sTemp = m_fnAutoSaveFile.GetFullPath();
383  if (m_pTimerAutoSaveCheckBoxCtrl->IsChecked()) {
384  if (!m_fnAutoSaveFile.IsOk() || m_fnAutoSaveFile.IsDir()) {
386  XO("Automatic Save path is invalid."),
387  XO("Error in Automatic Save"),
388  wxICON_EXCLAMATION | wxOK);
389  return;
390  }
391  }
392  if (m_pTimerAutoExportCheckBoxCtrl->IsChecked()) {
393  if (!m_fnAutoExportFile.IsOk() || m_fnAutoExportFile.IsDir()) {
395  XO("Automatic Export path is invalid."),
396  XO("Error in Automatic Export"),
397  wxICON_EXCLAMATION | wxOK);
398  return;
399  }
400  }
401 
402  // MY: Estimate here if we have enough disk space to
403  // complete this Timer Recording.
404  // If we dont think there is enough space then ask the user
405  // if they want to continue.
406  // We don't stop the user from starting the recording
407  // as its possible that they plan to free up some
408  // space before the recording begins
409  auto &projectManager = ProjectManager::Get( mProject );
410 
411  // How many minutes do we have left on the disc?
412  int iMinsLeft = projectManager.GetEstimatedRecordingMinsLeftOnDisk();
413 
414  // How many minutes will this recording require?
415  int iMinsRecording = m_TimeSpan_Duration.GetMinutes();
416 
417  // Do we have enough space?
418  if (iMinsRecording >= iMinsLeft) {
419 
420  // Format the strings
421  auto sRemainingTime = projectManager.GetHoursMinsString(iMinsLeft);
422  auto sPlannedTime = projectManager.GetHoursMinsString(iMinsRecording);
423 
424  // Create the message string
425  auto sMessage = XO(
426 "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")
427  .Format( sPlannedTime, sRemainingTime );
428 
429  AudacityMessageDialog dlgMessage(
430  nullptr,
431  sMessage,
432  XO("Timer Recording Disk Space Warning"),
433  wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
434  if (dlgMessage.ShowModal() != wxID_YES ) {
435  // User decided not to continue - bail out!
436  return;
437  }
438  }
439 
440  m_timer.Stop(); // Don't need to keep updating m_DateTime_Start to prevent backdating.
441  this->EndModal(wxID_OK);
442  wxLongLong duration = m_TimeSpan_Duration.GetSeconds();
443  // this will assert if the duration won't fit in a long
444  gPrefs->Write(wxT("/TimerRecord/LastDuration"), duration.ToLong());
445  gPrefs->Flush();
446 }
447 
448 void TimerRecordDialog::EnableDisableAutoControls(bool bEnable, int iControlGoup) {
449 
450  if (iControlGoup == CONTROL_GROUP_EXPORT) {
451  m_pTimerExportPathTextCtrl->Enable( bEnable );
452  m_pTimerExportPathButtonCtrl->Enable( bEnable);
453  } else if (iControlGoup == CONTROL_GROUP_SAVE) {
454  m_pTimerSavePathTextCtrl->Enable( bEnable);
455  m_pTimerSavePathButtonCtrl->Enable(bEnable );
456  }
457 
458  // Enable or disable the Choice box - if there is no Save or Export then this will be disabled
459  if (m_pTimerAutoSaveCheckBoxCtrl->GetValue() || m_pTimerAutoExportCheckBoxCtrl->GetValue()) {
461  } else {
464  }
465 }
466 
468  // Will update the text box controls
469  m_pTimerSavePathTextCtrl->SetValue(m_fnAutoSaveFile.GetFullPath());
470  m_pTimerExportPathTextCtrl->SetValue(m_fnAutoExportFile.GetFullPath());
471 
472  // MY: Ensure we still display "Current Project" if this has already been saved
474  m_pTimerSavePathTextCtrl->SetValue(_("Current Project"));
475  }
476 }
477 
481 {
482  auto updateResult = ProgressResult::Success;
483 
484  const auto gAudioIO = AudioIO::Get();
485  gAudioIO->DelayActions(true);
486  {
487  auto cleanup = finally([gAudioIO]{ gAudioIO->DelayActions(false); });
488 
489  if (m_DateTime_Start > wxDateTime::UNow())
490  updateResult = this->WaitForStart();
491 
492  if (updateResult != ProgressResult::Success) {
493  // Don't proceed, but don't treat it as canceled recording. User just canceled waiting.
495  } else {
496  // Record for specified time.
498  bool bIsRecording = true;
499 
500  auto sPostAction = Verbatim(
501  m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() );
502 
503  // Two column layout.
505  {
506  XO("Recording start:") ,
507  XO("Duration:") ,
508  XO("Recording end:") ,
509  {} ,
510  XO("Automatic Save enabled:") ,
511  XO("Automatic Export enabled:") ,
512  XO("Action after Timer Recording:") ,
513  },
514  {
516  Verbatim( m_TimeSpan_Duration.Format() ),
518  {} ,
519  (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) ,
520  (m_bAutoExportEnabled ? XO("Yes") : XO("No")) ,
521  sPostAction ,
522  }
523  };
524 
526  progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(),
527  XO("Audacity Timer Record Progress"),
528  columns,
530 
531  // Make sure that start and end time are updated, so we always get the full
532  // duration, even if there's some delay getting here.
533  wxTimerEvent dummyTimerEvent;
534  this->OnTimer(dummyTimerEvent);
535 
536  // Loop for progress display during recording.
537  while (bIsRecording && (updateResult == ProgressResult::Success)) {
538  updateResult = progress.UpdateProgress();
539  wxMilliSleep(kTimerInterval);
540  bIsRecording = (wxDateTime::UNow() <= m_DateTime_End); // Call UNow() again for extra accuracy...
541  }
542  }
543  }
544 
545  // Must do this AFTER the timer project dialog has been deleted to ensure the application
546  // responds to the AUDIOIO events...see not about bug #334 in the ProgressDialog constructor.
548 
549  // Let the caller handle cancellation or failure from recording progress.
550  if (updateResult == ProgressResult::Cancelled || updateResult == ProgressResult::Failed)
552 
553  return ExecutePostRecordActions((updateResult == ProgressResult::Stopped));
554 }
555 
557  // MY: We no longer automatically (and silently) call ->Save() when the
558  // timer recording is completed. We can now Save and/or Export depending
559  // on the options selected by the user.
560  // Once completed, we can also close Audacity, restart the system or
561  // shutdown the system.
562  // If there was any error with the auto save or export then we will not do
563  // the actions requested and instead present an error mesasge to the user.
564  // Finally, if there is no post-record action selected then we output
565  // a dialog detailing what has been carried out instead.
566 
567  bool bSaveOK = false;
568  bool bExportOK = false;
569  int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
570  int iOverriddenAction = iPostRecordAction;
571  bool bErrorOverride = false;
572 
573  // Do Automatic Save?
574  if (m_bAutoSaveEnabled) {
575 
576  auto &projectFileManager = ProjectFileManager::Get( mProject );
577  // MY: If this project has already been saved then simply execute a Save here
579  bSaveOK = projectFileManager.Save();
580  } else {
581  bSaveOK = projectFileManager.SaveFromTimerRecording(m_fnAutoSaveFile);
582  }
583  }
584 
585  // Do Automatic Export?
586  if (m_bAutoExportEnabled) {
587  Exporter e{ mProject };
588  bExportOK = e.ProcessFromTimerRecording(
589  false, 0.0, TrackList::Get( mProject ).GetEndTime(),
592  }
593 
594  // Check if we need to override the post recording action
595  bErrorOverride = ((m_bAutoSaveEnabled && !bSaveOK) || (m_bAutoExportEnabled && !bExportOK));
596  if (bErrorOverride || bWasStopped) {
597  iPostRecordAction = POST_TIMER_RECORD_NOTHING;
598  }
599 
600  if (iPostRecordAction == POST_TIMER_RECORD_NOTHING) {
601  // If there is no post-record action then we can show a message indicating what has been done
602 
603  auto sMessage = (bWasStopped ? XO("Timer Recording stopped.") :
604  XO("Timer Recording completed."));
605 
606  if (m_bAutoSaveEnabled) {
607  if (bSaveOK) {
608  sMessage = XO("%s\n\nRecording saved: %s").Format(
609  sMessage, m_fnAutoSaveFile.GetFullPath());
610  } else {
611  sMessage = XO("%s\n\nError saving recording.").Format( sMessage );
612  }
613  }
614  if (m_bAutoExportEnabled) {
615  if (bExportOK) {
616  sMessage = XO("%s\n\nRecording exported: %s").Format(
617  sMessage, m_fnAutoExportFile.GetFullPath());
618  } else {
619  sMessage = XO("%s\n\nError exporting recording.").Format( sMessage );
620  }
621  }
622 
623  if (bErrorOverride) {
624 
625  if ((iOverriddenAction != iPostRecordAction) &&
626  (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
627  // Inform the user that we have overridden the selected action
628  sMessage = XO("%s\n\n'%s' has been canceled due to the error(s) noted above.").Format(
629  sMessage,
630  m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
631  }
632 
633  // Show Error Message Box
635  sMessage,
636  XO("Error"),
637  wxICON_EXCLAMATION | wxOK);
638  } else {
639 
640  if (bWasStopped && (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
641  sMessage = XO("%s\n\n'%s' has been canceled as the recording was stopped.").Format(
642  sMessage,
643  m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
644  }
645 
647  sMessage,
648  XO("Timer Recording"),
649  wxICON_INFORMATION | wxOK);
650  }
651  }
652 
653  // MY: Lets do some actions that only apply to Exit/Restart/Shutdown
654  if (iPostRecordAction >= POST_TIMER_RECORD_CLOSE) {
655  do {
656 
657  // Set the flags as appropriate based on what we have done
658  wxUint32 eActionFlags = TR_ACTION_NOTHING;
659  if (m_bAutoSaveEnabled && bSaveOK) {
660  eActionFlags |= TR_ACTION_SAVED;
661  }
662  if (m_bAutoExportEnabled && bExportOK) {
663  eActionFlags |= TR_ACTION_EXPORTED;
664  }
665 
666  // Lets show a warning dialog telling the user what is about to happen.
667  // If the user no longer wants to carry out this action then they can click
668  // Cancel and we will do POST_TIMER_RECORD_NOTHING instead.
669  auto iDelayOutcome = PreActionDelay(iPostRecordAction, (TimerRecordCompletedActions)eActionFlags);
670  if (iDelayOutcome != ProgressResult::Success) {
671  // Cancel the action!
672  iPostRecordAction = POST_TIMER_RECORD_NOTHING;
673  break;
674  }
675  } while (false);
676  }
677 
678  // Return the action as required
679  return iPostRecordAction;
680 }
681 
683 {
684 #if defined(__WXMSW__)
685  // On Windows, wxWidgets uses the system date control and it displays the
686  // date based on the Windows locale selected by the user. But, wxDateTime
687  // using the strftime function to return the formatted date. Since the
688  // default locale for the Windows CRT environment is "C", the dates come
689  // back in a different format.
690  //
691  // So, we make direct Windows calls to format the date like it the date
692  // control.
693  //
694  // (Most of this taken from src/msw/datectrl.cpp)
695 
696  const wxDateTime::Tm tm(dt.GetTm());
697  SYSTEMTIME st;
698  wxString s;
699  int len;
700 
701  st.wYear = (WXWORD)tm.year;
702  st.wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1);
703  st.wDay = tm.mday;
704  st.wDayOfWeek = st.wMinute = st.wSecond = st.wMilliseconds = 0;
705 
706  len = ::GetDateFormat(LOCALE_USER_DEFAULT,
707  DATE_SHORTDATE,
708  &st,
709  NULL,
710  NULL,
711  0);
712  if (len > 0) {
713  len = ::GetDateFormat(LOCALE_USER_DEFAULT,
714  DATE_SHORTDATE,
715  &st,
716  NULL,
717  wxStringBuffer(s, len),
718  len);
719  if (len > 0) {
720  s += wxT(" ") + dt.FormatTime();
721  return Verbatim( s );
722  }
723  }
724 #endif
725 
726  // Use default formatting
727 wxPrintf(wxT("%s\n"), dt.Format());
728  return Verbatim( dt.FormatDate() + wxT(" ") + dt.FormatTime() );
729 }
730 
732  wxWindow *wParent, const int iID,
733  const TranslatableString &sCaption, const TranslatableString &sValue)
734 {
735  wxTextCtrlWrapper * pTextCtrl;
736  wxASSERT(wParent); // to justify safenew
737  pTextCtrl = safenew wxTextCtrlWrapper(wParent, iID, sValue.Translation());
738  pTextCtrl->SetName(sCaption.Translation());
739  return pTextCtrl;
740 }
741 
743 {
744  bool bAutoSave = gPrefs->ReadBool("/TimerRecord/AutoSave", false);
745  bool bAutoExport = gPrefs->ReadBool("/TimerRecord/AutoExport", false);
746  int iPostTimerRecordAction = gPrefs->ReadLong("/TimerRecord/PostAction", 0);
747 
748  S.SetBorder(5);
750  /* i18n-hint a format string for hours, minutes, and seconds */
751  auto strFormat = XO("099 h 060 m 060 s");
752  /* i18n-hint a format string for days, hours, minutes, and seconds */
753  auto strFormat1 = XO("099 days 024 h 060 m 060 s");
754 
755  S.StartMultiColumn(2, wxCENTER);
756  {
757  S.StartVerticalLay(true);
758  {
759  /* i18n-hint: This string is used to configure the controls for times when the recording is
760  * started and stopped. As such it is important that only the alphabetic parts of the string
761  * are translated, with the numbers left exactly as they are.
762  * The 'h' indicates the first number displayed is hours, the 'm' indicates the second number
763  * displayed is minutes, and the 's' indicates that the third number displayed is seconds.
764  */
765  S.StartStatic(XO("Start Date and Time"), true);
766  {
768  safenew wxDatePickerCtrl(S.GetParent(), // wxWindow *parent,
769  ID_DATEPICKER_START, // wxWindowID id,
770  m_DateTime_Start); // const wxDateTime& dt = wxDefaultDateTime,
771  // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
772  m_pDatePickerCtrl_Start->SetRange(wxDateTime::Today(), wxInvalidDateTime); // No backdating.
773 #if wxUSE_ACCESSIBILITY
774  m_pDatePickerCtrl_Start->SetAccessible( safenew DatePickerCtrlAx(m_pDatePickerCtrl_Start));
775 #endif
776  S.Name(XO("Start Date"))
778 
781  {}, 0, 44100,
782  Options{}
783  .MenuEnabled(false)
784  .Format(strFormat)
786  S.Name(XO("Start Time"))
788  }
789  S.EndStatic();
790 
791  S.StartStatic(XO("End Date and Time"), true);
792  {
794  safenew wxDatePickerCtrl(S.GetParent(), // wxWindow *parent,
795  ID_DATEPICKER_END, // wxWindowID id,
796  m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime,
797  // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
798  // long style = wxDP_DEFAULT | wxDP_SHOWCENTURY,
799  // const wxValidator& validator = wxDefaultValidator,
800  // const wxString& name = "datectrl")
801  m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
802 #if wxUSE_ACCESSIBILITY
803  m_pDatePickerCtrl_End->SetAccessible( safenew DatePickerCtrlAx(m_pDatePickerCtrl_End));
804 #endif
805  S.Name(XO("End Date"))
807 
810  {}, 0, 44100,
811  Options{}
812  .MenuEnabled(false)
813  .Format(strFormat)
815  S.Name(XO("End Time"))
817  }
818  S.EndStatic();
819 
820  S.StartStatic(XO("Duration"), true);
821  {
824  {}, 0, 44100,
825  Options{}
826  .MenuEnabled(false)
827  .Format(strFormat1)
828  .Value(true, m_TimeSpan_Duration.GetSeconds().ToDouble()));
829  /* i18n-hint: This string is used to configure the controls which shows the recording
830  * duration. As such it is important that only the alphabetic parts of the string
831  * are translated, with the numbers left exactly as they are.
832  * The string 'days' indicates that the first number in the control will be the number of days,
833  * then the 'h' indicates the second number displayed is hours, the 'm' indicates the third
834  * number displayed is minutes, and the 's' indicates that the fourth number displayed is
835  * seconds.
836  */
837  S.Name(XO("Duration"))
839  }
840  S.EndStatic();
841  }
842  S.EndVerticalLay();
843 
844  S.StartVerticalLay(true);
845  {
846  S.StartStatic(XO("Automatic Save"), true);
847  {
848  // If checked, the project will be saved when the recording is completed
849  m_pTimerAutoSaveCheckBoxCtrl = S.Id(ID_AUTOSAVE_CHECKBOX).AddCheckBox(XXO("Enable &Automatic Save?"),
850  bAutoSave);
851  S.StartMultiColumn(3, wxEXPAND);
852  {
853  TranslatableString sInitialValue;
854  auto sSaveValue = ProjectFileIO::Get(mProject).GetFileName();
855  if (!sSaveValue.empty()) {
856  m_fnAutoSaveFile.Assign(sSaveValue);
857  sInitialValue = XO("Current Project");
858  }
859  S.AddPrompt(XXO("Save Project As:"));
862  XO("Save Project As:"), sInitialValue);
866  }
867  S.EndMultiColumn();
868  }
869  S.EndStatic();
870 
871  S.StartStatic(XO("Automatic Export"), true);
872  {
873  m_pTimerAutoExportCheckBoxCtrl = S.Id(ID_AUTOEXPORT_CHECKBOX).AddCheckBox(XXO("Enable Automatic &Export?"), bAutoExport);
874  S.StartMultiColumn(3, wxEXPAND);
875  {
876  S.AddPrompt(XXO("Export Project As:"));
879  XO("Export Project As:"), {});
883  }
884  S.EndMultiColumn();
885  }
886  S.EndStatic();
887 
888  S.StartStatic(XO("Options"), true);
889  {
890 
891  S.StartMultiColumn(1, wxEXPAND);
892  {
893  S.SetStretchyCol( 0 );
894  m_pTimerAfterCompleteChoiceCtrl = S.AddChoice(XXO("After Recording completes:"),
895  {
896  XO("Do nothing") ,
897  XO("Exit Audacity") ,
898  #ifdef __WINDOWS__
899  XO("Restart system") ,
900  XO("Shutdown system") ,
901  #endif
902  },
903  iPostTimerRecordAction
904  );
905  }
906  S.EndMultiColumn();
907  }
908  S.EndStatic();
909 
910  }
911  S.EndVerticalLay();
912  }
913  S.EndMultiColumn();
914 
915  // MY: Added the help button here
917 
918  Layout();
919  Fit();
920  SetMinSize(GetSize());
921  Center();
922 
925 }
926 
928 {
929  double dTime;
930  long hr;
931  long min;
932  long sec;
933 
935  dTime = m_pTimeTextCtrl_Start->GetValue();
936  hr = (long)(dTime / 3600.0);
937  min = (long)((dTime - (hr * 3600.0)) / 60.0);
938  sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
939  m_DateTime_Start.SetHour(hr);
940  m_DateTime_Start.SetMinute(min);
941  m_DateTime_Start.SetSecond(sec);
942 
944  dTime = m_pTimeTextCtrl_End->GetValue();
945  hr = (long)(dTime / 3600.0);
946  min = (long)((dTime - (hr * 3600.0)) / 60.0);
947  sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
948  m_DateTime_End.SetHour(hr);
949  m_DateTime_End.SetMinute(min);
950  m_DateTime_End.SetSecond(sec);
951 
953 
954  // Pull the settings from the auto save/export controls and write to the pref file
957 
958  // MY: Obtain the index from the choice control so we can save to the prefs file
959  int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
960 
961  // Save the options back to the prefs file
962  gPrefs->Write("/TimerRecord/AutoSave", m_bAutoSaveEnabled);
963  gPrefs->Write("/TimerRecord/AutoExport", m_bAutoExportEnabled);
964  gPrefs->Write("/TimerRecord/PostAction", iPostRecordAction);
965 
966  return true;
967 }
968 
969 // Update m_TimeSpan_Duration and ctrl based on m_DateTime_Start and m_DateTime_End.
971 {
973  m_pTimeTextCtrl_Duration->SetValue(m_TimeSpan_Duration.GetSeconds().ToDouble());
974 }
975 
976 // Update m_DateTime_End and ctrls based on m_DateTime_Start and m_TimeSpan_Duration.
978 {
979  //v Use remaining disk -> record time calcs from AudacityProject::OnTimer to set range?
981  //wxLogDebug( "Time start %s end %s",
982  // m_DateTime_Start.FormatISOCombined(' '),
983  // m_DateTime_End.FormatISOCombined(' ') );
984 
985  // Disable the range limitation (to fix Bug 1749 and 1978)
986  // Otherwise SetVallue asserts when going back in time.
987  m_pDatePickerCtrl_End->SetRange(wxInvalidDateTime, wxInvalidDateTime);
989  // Re-enable range limitation to constrain user input.
990  m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
991  m_pDatePickerCtrl_End->Refresh();
993 }
994 
996 {
997  // MY: The Waiting For Start dialog now shows what actions will occur after recording has completed
998  auto sPostAction = Verbatim(
999  m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() );
1000 
1001  // Two column layout.
1003  {
1004  XO("Waiting to start recording at:") ,
1005  XO("Recording duration:") ,
1006  XO("Scheduled to stop at:") ,
1007  {} ,
1008  XO("Automatic Save enabled:") ,
1009  XO("Automatic Export enabled:") ,
1010  XO("Action after Timer Recording:") ,
1011  },
1012  {
1014  Verbatim( m_TimeSpan_Duration.Format() ),
1016  {} ,
1017  (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) ,
1018  (m_bAutoExportEnabled ? XO("Yes") : XO("No")) ,
1019  sPostAction ,
1020  },
1021  };
1022 
1023  wxDateTime startWait_DateTime = wxDateTime::UNow();
1024  wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime;
1025  TimerProgressDialog progress(waitDuration.GetMilliseconds().GetValue(),
1026  XO("Audacity Timer Record - Waiting for Start"),
1027  columns,
1029  /* i18n-hint: "in" means after a duration of time,
1030  which is shown below this string */
1031  XO("Recording will commence in:"));
1032 
1033  auto updateResult = ProgressResult::Success;
1034  bool bIsRecording = false;
1035  while (updateResult == ProgressResult::Success && !bIsRecording)
1036  {
1037  updateResult = progress.UpdateProgress();
1038  wxMilliSleep(kTimerInterval);
1039  bIsRecording = (m_DateTime_Start <= wxDateTime::UNow());
1040  }
1041  return updateResult;
1042 }
1043 
1045 {
1047  ->GetString(iActionIndex) );
1048 
1049  /* i18n-hint: %s is one of "Do nothing", "Exit Audacity", "Restart system",
1050  or "Shutdown system", and
1051  "in" means after a duration of time, shown below this string */
1052  auto sCountdownLabel = XO("%s in:").Format( sAction );
1053 
1054  // Two column layout.
1056  {
1057  XO("Timer Recording completed.") ,
1058  {} ,
1059  XO("Recording Saved:") ,
1060  XO("Recording Exported:") ,
1061  XO("Action after Timer Recording:") ,
1062  },
1063  {
1064  {} ,
1065  {} ,
1066  ((eCompletedActions & TR_ACTION_SAVED) ? XO("Yes") : XO("No")) ,
1067  ((eCompletedActions & TR_ACTION_EXPORTED) ? XO("Yes") : XO("No")) ,
1068  sAction ,
1069  },
1070  };
1071 
1072 
1073  wxDateTime dtNow = wxDateTime::UNow();
1074  wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
1075  wxDateTime dtActionTime = dtNow.Add(tsWait);
1076 
1077  TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
1078  XO("Audacity Timer Record - Waiting"),
1079  columns,
1081  sCountdownLabel);
1082 
1083  auto iUpdateResult = ProgressResult::Success;
1084  bool bIsTime = false;
1085  while (iUpdateResult == ProgressResult::Success && !bIsTime)
1086  {
1087  iUpdateResult = dlgAction.UpdateProgress();
1088  wxMilliSleep(kTimerInterval);
1089  bIsTime = (dtActionTime <= wxDateTime::UNow());
1090  }
1091  return iUpdateResult;
1092 }
TimerRecordDialog::m_pTimeTextCtrl_Duration
NumericTextCtrl * m_pTimeTextCtrl_Duration
Definition: TimerRecordDialog.h:121
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
TimerRecordDialog::m_timer
wxTimer m_timer
Definition: TimerRecordDialog.h:123
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
TimerRecordDialog::m_fnAutoSaveFile
wxFileName m_fnAutoSaveFile
Definition: TimerRecordDialog.h:141
TimerRecordDialog.h
ShuttleGuiBase::AddChoice
wxChoice * AddChoice(const TranslatableString &Prompt, const TranslatableStrings &choices, int Selected=-1)
Definition: ShuttleGui.cpp:398
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
TimerRecordDialog::UpdateEnd
void UpdateEnd()
Definition: TimerRecordDialog.cpp:977
ProjectFileIO::GetFileName
const FilePath & GetFileName() const
Definition: ProjectFileIO.cpp:1487
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:309
TimerRecordDialog::OnAutoExportPathButton_Click
void OnAutoExportPathButton_Click(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:339
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Message"), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
BasicUI::ProgressResult::Success
@ Success
ProjectFileIO.h
ProjectAudioManager::Get
static ProjectAudioManager & Get(AudacityProject &project)
Definition: ProjectAudioManager.cpp:50
ProjectAudioManager::OnRecord
void OnRecord(bool altAppearance)
Definition: ProjectAudioManager.cpp:466
TimerRecordDialog::m_pTimerAutoExportCheckBoxCtrl
wxCheckBox * m_pTimerAutoExportCheckBoxCtrl
Definition: TimerRecordDialog.h:129
HelpSystem.h
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
TimerRecordDialog::OnTimeText_End
void OnTimeText_End(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:269
eHelpButton
@ eHelpButton
Definition: ShuttleGui.h:604
ID_AUTOSAVE_CHECKBOX
@ ID_AUTOSAVE_CHECKBOX
Definition: TimerRecordDialog.cpp:73
TimerProgressDialog::UpdateProgress
ProgressResult UpdateProgress()
Definition: ProgressDialog.cpp:1670
ID_DATEPICKER_START
@ ID_DATEPICKER_START
Definition: TimerRecordDialog.cpp:64
pdlgHideStopButton
@ pdlgHideStopButton
Definition: ProgressDialog.h:38
Exporter
Definition: Export.h:166
BasicUI::ProgressResult
ProgressResult
Definition: BasicUI.h:145
TimerRecordDialog::OnHelpButtonClick
void OnHelpButtonClick(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:364
TimerRecordDialog::OnDatePicker_Start
void OnDatePicker_Start(wxDateEvent &event)
Definition: TimerRecordDialog.cpp:205
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
XO
#define XO(s)
Definition: Internat.h:31
ID_AUTOSAVEPATH_TEXT
@ ID_AUTOSAVEPATH_TEXT
Definition: TimerRecordDialog.cpp:70
ProjectFileIO::Get
static ProjectFileIO & Get(AudacityProject &project)
Definition: ProjectFileIO.cpp:269
ProgressDialog.h
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1238
TimerRecordDialog::m_pTimerExportPathButtonCtrl
wxButton * m_pTimerExportPathButtonCtrl
Definition: TimerRecordDialog.h:131
TimerRecordDialog::OnOK
void OnOK(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:369
ProjectAudioManager.h
TimerRecordDialog::RunWaitDialog
int RunWaitDialog()
Runs the wait for start dialog. Returns false if the user clicks stop.
Definition: TimerRecordDialog.cpp:480
TimerRecordDialog::UpdateDuration
void UpdateDuration()
Definition: TimerRecordDialog.cpp:970
NumericTextCtrl
Definition: NumericTextCtrl.h:172
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
NumericTextCtrl::SetValue
void SetValue(double newValue)
Definition: NumericTextCtrl.cpp:1472
TimerRecordDialog::OnAutoSavePathButton_Click
void OnAutoSavePathButton_Click(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:301
AudacityMessageDialog
Wrap wxMessageDialog so that caption IS translatable.
Definition: wxPanelWrapper.h:215
ID_TIMETEXT_DURATION
@ ID_TIMETEXT_DURATION
Definition: TimerRecordDialog.cpp:68
FileNames::AudacityProjects
AUDACITY_DLL_API const FileType AudacityProjects
Definition: FileNames.h:75
TR_ACTION_SAVED
@ TR_ACTION_SAVED
Definition: TimerRecordDialog.h:35
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
POST_TIMER_RECORD_CLOSE
@ POST_TIMER_RECORD_CLOSE
Definition: TimerRecordDialog.h:45
ID_AUTOEXPORTPATH_BUTTON
@ ID_AUTOEXPORTPATH_BUTTON
Definition: TimerRecordDialog.cpp:71
ID_AUTOEXPORTPATH_TEXT
@ ID_AUTOEXPORTPATH_TEXT
Definition: TimerRecordDialog.cpp:72
TimerRecordDialog::UpdateTextBoxControls
void UpdateTextBoxControls()
Definition: TimerRecordDialog.cpp:467
TimerRecordDialog::m_bAutoExportEnabled
bool m_bAutoExportEnabled
Definition: TimerRecordDialog.h:142
pdlgHideElapsedTime
@ pdlgHideElapsedTime
Definition: ProgressDialog.h:40
TR_ACTION_NOTHING
@ TR_ACTION_NOTHING
Definition: TimerRecordDialog.h:34
ProjectManager::Get
static ProjectManager & Get(AudacityProject &project)
Definition: ProjectManager.cpp:67
TimerRecordDialog::m_bAutoSaveEnabled
bool m_bAutoSaveEnabled
Definition: TimerRecordDialog.h:140
wxTextCtrlWrapper
Definition: wxTextCtrlWrapper.h:23
XXO
#define XXO(s)
Definition: Internat.h:44
eCancelButton
@ eCancelButton
Definition: ShuttleGui.h:601
TimerRecordDialog::ExecutePostRecordActions
int ExecutePostRecordActions(bool bWasStopped)
Definition: TimerRecordDialog.cpp:556
ID_TIMETEXT_START
@ ID_TIMETEXT_START
Definition: TimerRecordDialog.cpp:65
kSlowTimerInterval
const int kSlowTimerInterval
Definition: TimerRecordDialog.cpp:84
POST_TIMER_RECORD_NOTHING
@ POST_TIMER_RECORD_NOTHING
Definition: TimerRecordDialog.h:44
TR_ACTION_EXPORTED
@ TR_ACTION_EXPORTED
Definition: TimerRecordDialog.h:36
ID_DATEPICKER_END
@ ID_DATEPICKER_END
Definition: TimerRecordDialog.cpp:66
ProjectFileManager::Get
static ProjectFileManager & Get(AudacityProject &project)
Definition: ProjectFileManager.cpp:61
TimerRecordDialog::NewPathControl
wxTextCtrlWrapper * NewPathControl(wxWindow *wParent, const int iID, const TranslatableString &sCaption, const TranslatableString &sValue)
Definition: TimerRecordDialog.cpp:731
wxTextCtrlWrapper.h
TimerRecordDialog::OnTimeText_Duration
void OnTimeText_Duration(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:289
TimerRecordDialog::m_iAutoExportFilterIndex
int m_iAutoExportFilterIndex
Definition: TimerRecordDialog.h:146
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1229
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
TimerProgressDialog
Definition: ProgressDialog.h:152
wxDateTime_to_AudacityTime
static double wxDateTime_to_AudacityTime(wxDateTime &dateTime)
Definition: TimerRecordDialog.cpp:89
TimerRecordDialog::WaitForStart
ProgressResult WaitForStart()
Definition: TimerRecordDialog.cpp:995
ProgressDialog::MessageTable
std::vector< MessageColumn > MessageTable
Definition: ProgressDialog.h:62
TimerRecordDialog::m_pTimerSavePathTextCtrl
wxTextCtrlWrapper * m_pTimerSavePathTextCtrl
Definition: TimerRecordDialog.h:127
pdlgConfirmStopCancel
@ pdlgConfirmStopCancel
Definition: ProgressDialog.h:41
TimerRecordDialog::m_pTimerSavePathButtonCtrl
wxButton * m_pTimerSavePathButtonCtrl
Definition: TimerRecordDialog.h:128
NumericConverter::TIME
@ TIME
Definition: NumericTextCtrl.h:52
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
TimerRecordDialog::m_DateTime_Start
wxDateTime m_DateTime_Start
Definition: TimerRecordDialog.h:110
@0::kTimerInterval
@ kTimerInterval
ProjectFileManager.h
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:299
TimerRecordDialog::PreActionDelay
ProgressResult PreActionDelay(int iActionIndex, TimerRecordCompletedActions eCompletedActions)
Definition: TimerRecordDialog.cpp:1044
TimerRecordDialog::m_bProjectAlreadySaved
bool m_bProjectAlreadySaved
Definition: TimerRecordDialog.h:147
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
ID_AUTOSAVEPATH_BUTTON
@ ID_AUTOSAVEPATH_BUTTON
Definition: TimerRecordDialog.cpp:69
TimerRecordDialog::m_pDatePickerCtrl_Start
wxDatePickerCtrl * m_pDatePickerCtrl_Start
Definition: TimerRecordDialog.h:115
TimerRecordDialog::mProject
AudacityProject & mProject
Definition: TimerRecordDialog.h:108
TimerRecordDialog::m_DateTime_End
wxDateTime m_DateTime_End
Definition: TimerRecordDialog.h:111
ShuttleGui.h
ProjectAudioManager::Stop
void Stop(bool stopStream=true)
Definition: ProjectAudioManager.cpp:311
ProjectManager.h
TimerRecordDialog::OnTimer
void OnTimer(wxTimerEvent &event)
Definition: TimerRecordDialog.cpp:194
TimerRecordDialog::OnDatePicker_End
void OnDatePicker_End(wxDateEvent &event)
Definition: TimerRecordDialog.cpp:247
CONTROL_GROUP_EXPORT
@ CONTROL_GROUP_EXPORT
Definition: TimerRecordDialog.cpp:79
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
TimerRecordDialog::OnAutoSaveCheckBox_Change
void OnAutoSaveCheckBox_Change(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:356
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
TimerRecordDialog::~TimerRecordDialog
~TimerRecordDialog()
Definition: TimerRecordDialog.cpp:190
ID_AUTOEXPORT_CHECKBOX
@ ID_AUTOEXPORT_CHECKBOX
Definition: TimerRecordDialog.cpp:74
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:663
wxDialogWrapper
Definition: wxPanelWrapper.h:81
WindowAccessible.h
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
eOkButton
@ eOkButton
Definition: ShuttleGui.h:600
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
FileNames::SelectFile
AUDACITY_DLL_API FilePath SelectFile(Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
TimerRecordDialog::EnableDisableAutoControls
void EnableDisableAutoControls(bool bEnable, int iControlGoup)
Definition: TimerRecordDialog.cpp:448
POST_TIMER_RECORD_CANCEL
@ POST_TIMER_RECORD_CANCEL
Definition: TimerRecordDialog.h:42
_
#define _(s)
Definition: Internat.h:75
AudioIO.h
TIMER_ID
#define TIMER_ID
Definition: TimerRecordDialog.cpp:61
TimerRecordDialog::m_pTimeTextCtrl_Start
NumericTextCtrl * m_pTimeTextCtrl_Start
Definition: TimerRecordDialog.h:116
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:113
kTimerInterval
const int kTimerInterval
Definition: TimerRecordDialog.cpp:87
TimerRecordCompletedActions
TimerRecordCompletedActions
Definition: TimerRecordDialog.h:33
FileNames.h
wxTextCtrlWrapper::SetReadOnly
void SetReadOnly(bool readonly=true)
Definition: wxTextCtrlWrapper.h:66
AudacityMessageBox.h
TimerRecordDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: TimerRecordDialog.cpp:742
TimerRecordDialog::m_iAutoExportSubFormat
int m_iAutoExportSubFormat
Definition: TimerRecordDialog.h:145
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
NumericTextCtrl.h
TimerRecordDialog::m_pDatePickerCtrl_End
wxDatePickerCtrl * m_pDatePickerCtrl_End
Definition: TimerRecordDialog.h:118
TimerRecordDialog::m_pTimerAfterCompleteChoiceCtrl
wxChoice * m_pTimerAfterCompleteChoiceCtrl
Definition: TimerRecordDialog.h:134
Track.h
declares abstract base class Track, TrackList, and iterators over TrackList
TimerRecordDialog::m_TimeSpan_Duration
wxTimeSpan m_TimeSpan_Duration
Definition: TimerRecordDialog.h:112
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2432
Prefs.h
TimerRecordDialog::m_fnAutoExportFile
wxFileName m_fnAutoExportFile
Definition: TimerRecordDialog.h:143
ShuttleGuiBase::AddPrompt
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:238
TimerRecordDialog::m_pTimeTextCtrl_End
NumericTextCtrl * m_pTimeTextCtrl_End
Definition: TimerRecordDialog.h:119
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
TimerRecordDialog
Dialog for Timer Record, i.e., timed or long recording.
Definition: TimerRecordDialog.h:56
TimerRecordDialog::OnTimeText_Start
void OnTimeText_Start(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:227
TimerRecordDialog::GetDisplayDate
TranslatableString GetDisplayDate(wxDateTime &dt)
Definition: TimerRecordDialog.cpp:682
POST_TIMER_RECORD_CANCEL_WAIT
@ POST_TIMER_RECORD_CANCEL_WAIT
Definition: TimerRecordDialog.h:41
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
AudioIO::Get
static AudioIO * Get()
Definition: AudioIO.cpp:505
safenew
#define safenew
Definition: MemoryX.h:10
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:202
TimerRecordDialog::m_iAutoExportFormat
int m_iAutoExportFormat
Definition: TimerRecordDialog.h:144
NumericConverter::GetValue
double GetValue()
Definition: NumericTextCtrl.cpp:1172
anonymous_namespace{Menus.cpp}::Options
std::vector< CommandFlagOptions > & Options()
Definition: Menus.cpp:526
END_EVENT_TABLE
END_EVENT_TABLE()
TimerRecordDialog::m_pTimerExportPathTextCtrl
wxTextCtrlWrapper * m_pTimerExportPathTextCtrl
Definition: TimerRecordDialog.h:130
TimerRecordDialog::m_pTimerAutoSaveCheckBoxCtrl
wxCheckBox * m_pTimerAutoSaveCheckBoxCtrl
Definition: TimerRecordDialog.h:126
pdlgHideCancelButton
@ pdlgHideCancelButton
Definition: ProgressDialog.h:39
TimerRecordDialog::OnAutoExportCheckBox_Change
void OnAutoExportCheckBox_Change(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:360
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
ID_TIMETEXT_END
@ ID_TIMETEXT_END
Definition: TimerRecordDialog.cpp:67
CONTROL_GROUP_SAVE
@ CONTROL_GROUP_SAVE
Definition: TimerRecordDialog.cpp:78
TimerRecordDialog::TransferDataFromWindow
bool TransferDataFromWindow() override
Definition: TimerRecordDialog.cpp:927