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 "ShuttleGui.h"
44 #include "ProjectAudioManager.h"
45 #include "ProjectFileIO.h"
46 #include "ProjectFileManager.h"
47 #include "ProjectManager.h"
48 #include "Prefs.h"
49 #include "Track.h"
51 #include "widgets/HelpSystem.h"
53 #include "widgets/ErrorDialog.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, wxT("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  if (m_DateTime_Start > wxDateTime::UNow())
485  updateResult = this->WaitForStart();
486 
487  if (updateResult != ProgressResult::Success) {
488  // Don't proceed, but don't treat it as canceled recording. User just canceled waiting.
490  } else {
491  // Record for specified time.
493  bool bIsRecording = true;
494 
495  auto sPostAction = Verbatim(
496  m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() );
497 
498  // Two column layout.
500  {
501  XO("Recording start:") ,
502  XO("Duration:") ,
503  XO("Recording end:") ,
504  {} ,
505  XO("Automatic Save enabled:") ,
506  XO("Automatic Export enabled:") ,
507  XO("Action after Timer Recording:") ,
508  },
509  {
511  Verbatim( m_TimeSpan_Duration.Format() ),
513  {} ,
514  (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) ,
515  (m_bAutoExportEnabled ? XO("Yes") : XO("No")) ,
516  sPostAction ,
517  }
518  };
519 
521  progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(),
522  XO("Audacity Timer Record Progress"),
523  columns,
525 
526  // Make sure that start and end time are updated, so we always get the full
527  // duration, even if there's some delay getting here.
528  wxTimerEvent dummyTimerEvent;
529  this->OnTimer(dummyTimerEvent);
530 
531  // Loop for progress display during recording.
532  while (bIsRecording && (updateResult == ProgressResult::Success)) {
533  updateResult = progress.UpdateProgress();
534  wxMilliSleep(kTimerInterval);
535  bIsRecording = (wxDateTime::UNow() <= m_DateTime_End); // Call UNow() again for extra accuracy...
536  }
537  }
538 
539  // Must do this AFTER the timer project dialog has been deleted to ensure the application
540  // responds to the AUDIOIO events...see not about bug #334 in the ProgressDialog constructor.
542 
543  // Let the caller handle cancellation or failure from recording progress.
544  if (updateResult == ProgressResult::Cancelled || updateResult == ProgressResult::Failed)
546 
547  return ExecutePostRecordActions((updateResult == ProgressResult::Stopped));
548 }
549 
551  // MY: We no longer automatically (and silently) call ->Save() when the
552  // timer recording is completed. We can now Save and/or Export depending
553  // on the options selected by the user.
554  // Once completed, we can also close Audacity, restart the system or
555  // shutdown the system.
556  // If there was any error with the auto save or export then we will not do
557  // the actions requested and instead present an error mesasge to the user.
558  // Finally, if there is no post-record action selected then we output
559  // a dialog detailing what has been carried out instead.
560 
561  bool bSaveOK = false;
562  bool bExportOK = false;
563  int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
564  int iOverriddenAction = iPostRecordAction;
565  bool bErrorOverride = false;
566 
567  // Do Automatic Save?
568  if (m_bAutoSaveEnabled) {
569 
570  auto &projectFileManager = ProjectFileManager::Get( mProject );
571  // MY: If this project has already been saved then simply execute a Save here
573  bSaveOK = projectFileManager.Save();
574  } else {
575  bSaveOK = projectFileManager.SaveFromTimerRecording(m_fnAutoSaveFile);
576  }
577  }
578 
579  // Do Automatic Export?
580  if (m_bAutoExportEnabled) {
581  Exporter e{ mProject };
582  bExportOK = e.ProcessFromTimerRecording(
583  false, 0.0, TrackList::Get( mProject ).GetEndTime(),
586  }
587 
588  // Check if we need to override the post recording action
589  bErrorOverride = ((m_bAutoSaveEnabled && !bSaveOK) || (m_bAutoExportEnabled && !bExportOK));
590  if (bErrorOverride || bWasStopped) {
591  iPostRecordAction = POST_TIMER_RECORD_NOTHING;
592  }
593 
594  if (iPostRecordAction == POST_TIMER_RECORD_NOTHING) {
595  // If there is no post-record action then we can show a message indicating what has been done
596 
597  auto sMessage = (bWasStopped ? XO("Timer Recording stopped.") :
598  XO("Timer Recording completed."));
599 
600  if (m_bAutoSaveEnabled) {
601  if (bSaveOK) {
602  sMessage = XO("%s\n\nRecording saved: %s").Format(
603  sMessage, m_fnAutoSaveFile.GetFullPath());
604  } else {
605  sMessage = XO("%s\n\nError saving recording.").Format( sMessage );
606  }
607  }
608  if (m_bAutoExportEnabled) {
609  if (bExportOK) {
610  sMessage = XO("%s\n\nRecording exported: %s").Format(
611  sMessage, m_fnAutoExportFile.GetFullPath());
612  } else {
613  sMessage = XO("%s\n\nError exporting recording.").Format( sMessage );
614  }
615  }
616 
617  if (bErrorOverride) {
618 
619  if ((iOverriddenAction != iPostRecordAction) &&
620  (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
621  // Inform the user that we have overridden the selected action
622  sMessage = XO("%s\n\n'%s' has been canceled due to the error(s) noted above.").Format(
623  sMessage,
624  m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
625  }
626 
627  // Show Error Message Box
629  sMessage,
630  XO("Error"),
631  wxICON_EXCLAMATION | wxOK);
632  } else {
633 
634  if (bWasStopped && (iOverriddenAction != POST_TIMER_RECORD_NOTHING)) {
635  sMessage = XO("%s\n\n'%s' has been canceled as the recording was stopped.").Format(
636  sMessage,
637  m_pTimerAfterCompleteChoiceCtrl->GetString(iOverriddenAction));
638  }
639 
641  sMessage,
642  XO("Timer Recording"),
643  wxICON_INFORMATION | wxOK);
644  }
645  }
646 
647  // MY: Lets do some actions that only apply to Exit/Restart/Shutdown
648  if (iPostRecordAction >= POST_TIMER_RECORD_CLOSE) {
649  do {
650 
651  // Set the flags as appropriate based on what we have done
652  wxUint32 eActionFlags = TR_ACTION_NOTHING;
653  if (m_bAutoSaveEnabled && bSaveOK) {
654  eActionFlags |= TR_ACTION_SAVED;
655  }
656  if (m_bAutoExportEnabled && bExportOK) {
657  eActionFlags |= TR_ACTION_EXPORTED;
658  }
659 
660  // Lets show a warning dialog telling the user what is about to happen.
661  // If the user no longer wants to carry out this action then they can click
662  // Cancel and we will do POST_TIMER_RECORD_NOTHING instead.
663  auto iDelayOutcome = PreActionDelay(iPostRecordAction, (TimerRecordCompletedActions)eActionFlags);
664  if (iDelayOutcome != ProgressResult::Success) {
665  // Cancel the action!
666  iPostRecordAction = POST_TIMER_RECORD_NOTHING;
667  break;
668  }
669  } while (false);
670  }
671 
672  // Return the action as required
673  return iPostRecordAction;
674 }
675 
677 {
678 #if defined(__WXMSW__)
679  // On Windows, wxWidgets uses the system date control and it displays the
680  // date based on the Windows locale selected by the user. But, wxDateTime
681  // using the strftime function to return the formatted date. Since the
682  // default locale for the Windows CRT environment is "C", the dates come
683  // back in a different format.
684  //
685  // So, we make direct Windows calls to format the date like it the date
686  // control.
687  //
688  // (Most of this taken from src/msw/datectrl.cpp)
689 
690  const wxDateTime::Tm tm(dt.GetTm());
691  SYSTEMTIME st;
692  wxString s;
693  int len;
694 
695  st.wYear = (WXWORD)tm.year;
696  st.wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1);
697  st.wDay = tm.mday;
698  st.wDayOfWeek = st.wMinute = st.wSecond = st.wMilliseconds = 0;
699 
700  len = ::GetDateFormat(LOCALE_USER_DEFAULT,
701  DATE_SHORTDATE,
702  &st,
703  NULL,
704  NULL,
705  0);
706  if (len > 0) {
707  len = ::GetDateFormat(LOCALE_USER_DEFAULT,
708  DATE_SHORTDATE,
709  &st,
710  NULL,
711  wxStringBuffer(s, len),
712  len);
713  if (len > 0) {
714  s += wxT(" ") + dt.FormatTime();
715  return Verbatim( s );
716  }
717  }
718 #endif
719 
720  // Use default formatting
721 wxPrintf(wxT("%s\n"), dt.Format());
722  return Verbatim( dt.FormatDate() + wxT(" ") + dt.FormatTime() );
723 }
724 
726  wxWindow *wParent, const int iID,
727  const TranslatableString &sCaption, const TranslatableString &sValue)
728 {
729  wxTextCtrlWrapper * pTextCtrl;
730  wxASSERT(wParent); // to justify safenew
731  pTextCtrl = safenew wxTextCtrlWrapper(wParent, iID, sValue.Translation());
732  pTextCtrl->SetName(sCaption.Translation());
733  return pTextCtrl;
734 }
735 
737 {
738  bool bAutoSave = gPrefs->ReadBool("/TimerRecord/AutoSave", false);
739  bool bAutoExport = gPrefs->ReadBool("/TimerRecord/AutoExport", false);
740  int iPostTimerRecordAction = gPrefs->ReadLong("/TimerRecord/PostAction", 0);
741 
742  S.SetBorder(5);
744  /* i18n-hint a format string for hours, minutes, and seconds */
745  auto strFormat = XO("099 h 060 m 060 s");
746  /* i18n-hint a format string for days, hours, minutes, and seconds */
747  auto strFormat1 = XO("099 days 024 h 060 m 060 s");
748 
749  S.StartMultiColumn(2, wxCENTER);
750  {
751  S.StartVerticalLay(true);
752  {
753  /* i18n-hint: This string is used to configure the controls for times when the recording is
754  * started and stopped. As such it is important that only the alphabetic parts of the string
755  * are translated, with the numbers left exactly as they are.
756  * The 'h' indicates the first number displayed is hours, the 'm' indicates the second number
757  * displayed is minutes, and the 's' indicates that the third number displayed is seconds.
758  */
759  S.StartStatic(XO("Start Date and Time"), true);
760  {
762  safenew wxDatePickerCtrl(S.GetParent(), // wxWindow *parent,
763  ID_DATEPICKER_START, // wxWindowID id,
764  m_DateTime_Start); // const wxDateTime& dt = wxDefaultDateTime,
765  // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl")
766  m_pDatePickerCtrl_Start->SetRange(wxDateTime::Today(), wxInvalidDateTime); // No backdating.
767 #if wxUSE_ACCESSIBILITY
768  m_pDatePickerCtrl_Start->SetAccessible( safenew DatePickerCtrlAx(m_pDatePickerCtrl_Start));
769 #endif
770  S.Name(XO("Start Date"))
772 
775  {}, 0, 44100,
776  Options{}
777  .MenuEnabled(false)
778  .Format(strFormat)
780  S.Name(XO("Start Time"))
782  }
783  S.EndStatic();
784 
785  S.StartStatic(XO("End Date and Time"), true);
786  {
788  safenew wxDatePickerCtrl(S.GetParent(), // wxWindow *parent,
789  ID_DATEPICKER_END, // wxWindowID id,
790  m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime,
791  // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
792  // long style = wxDP_DEFAULT | wxDP_SHOWCENTURY,
793  // const wxValidator& validator = wxDefaultValidator,
794  // const wxString& name = "datectrl")
795  m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
796 #if wxUSE_ACCESSIBILITY
797  m_pDatePickerCtrl_End->SetAccessible( safenew DatePickerCtrlAx(m_pDatePickerCtrl_End));
798 #endif
799  S.Name(XO("End Date"))
801 
804  {}, 0, 44100,
805  Options{}
806  .MenuEnabled(false)
807  .Format(strFormat)
809  S.Name(XO("End Time"))
811  }
812  S.EndStatic();
813 
814  S.StartStatic(XO("Duration"), true);
815  {
818  {}, 0, 44100,
819  Options{}
820  .MenuEnabled(false)
821  .Format(strFormat1)
822  .Value(true, m_TimeSpan_Duration.GetSeconds().ToDouble()));
823  /* i18n-hint: This string is used to configure the controls which shows the recording
824  * duration. As such it is important that only the alphabetic parts of the string
825  * are translated, with the numbers left exactly as they are.
826  * The string 'days' indicates that the first number in the control will be the number of days,
827  * then the 'h' indicates the second number displayed is hours, the 'm' indicates the third
828  * number displayed is minutes, and the 's' indicates that the fourth number displayed is
829  * seconds.
830  */
831  S.Name(XO("Duration"))
833  }
834  S.EndStatic();
835  }
836  S.EndVerticalLay();
837 
838  S.StartVerticalLay(true);
839  {
840  S.StartStatic(XO("Automatic Save"), true);
841  {
842  // If checked, the project will be saved when the recording is completed
843  m_pTimerAutoSaveCheckBoxCtrl = S.Id(ID_AUTOSAVE_CHECKBOX).AddCheckBox(XXO("Enable &Automatic Save?"),
844  bAutoSave);
845  S.StartMultiColumn(3, wxEXPAND);
846  {
847  TranslatableString sInitialValue;
848  auto sSaveValue = ProjectFileIO::Get(mProject).GetFileName();
849  if (!sSaveValue.empty()) {
850  m_fnAutoSaveFile.Assign(sSaveValue);
851  sInitialValue = XO("Current Project");
852  }
853  S.AddPrompt(XXO("Save Project As:"));
856  XO("Save Project As:"), sInitialValue);
860  }
861  S.EndMultiColumn();
862  }
863  S.EndStatic();
864 
865  S.StartStatic(XO("Automatic Export"), true);
866  {
867  m_pTimerAutoExportCheckBoxCtrl = S.Id(ID_AUTOEXPORT_CHECKBOX).AddCheckBox(XXO("Enable Automatic &Export?"), bAutoExport);
868  S.StartMultiColumn(3, wxEXPAND);
869  {
870  S.AddPrompt(XXO("Export Project As:"));
873  XO("Export Project As:"), {});
877  }
878  S.EndMultiColumn();
879  }
880  S.EndStatic();
881 
882  S.StartStatic(XO("Options"), true);
883  {
884 
885  S.StartMultiColumn(1, wxEXPAND);
886  {
887  S.SetStretchyCol( 0 );
888  m_pTimerAfterCompleteChoiceCtrl = S.AddChoice(XXO("After Recording completes:"),
889  {
890  XO("Do nothing") ,
891  XO("Exit Audacity") ,
892  #ifdef __WINDOWS__
893  XO("Restart system") ,
894  XO("Shutdown system") ,
895  #endif
896  },
897  iPostTimerRecordAction
898  );
899  }
900  S.EndMultiColumn();
901  }
902  S.EndStatic();
903 
904  }
905  S.EndVerticalLay();
906  }
907  S.EndMultiColumn();
908 
909  // MY: Added the help button here
911 
912  Layout();
913  Fit();
914  SetMinSize(GetSize());
915  Center();
916 
919 }
920 
922 {
923  double dTime;
924  long hr;
925  long min;
926  long sec;
927 
929  dTime = m_pTimeTextCtrl_Start->GetValue();
930  hr = (long)(dTime / 3600.0);
931  min = (long)((dTime - (hr * 3600.0)) / 60.0);
932  sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
933  m_DateTime_Start.SetHour(hr);
934  m_DateTime_Start.SetMinute(min);
935  m_DateTime_Start.SetSecond(sec);
936 
938  dTime = m_pTimeTextCtrl_End->GetValue();
939  hr = (long)(dTime / 3600.0);
940  min = (long)((dTime - (hr * 3600.0)) / 60.0);
941  sec = (long)(dTime - (hr * 3600.0) - (min * 60.0));
942  m_DateTime_End.SetHour(hr);
943  m_DateTime_End.SetMinute(min);
944  m_DateTime_End.SetSecond(sec);
945 
947 
948  // Pull the settings from the auto save/export controls and write to the pref file
951 
952  // MY: Obtain the index from the choice control so we can save to the prefs file
953  int iPostRecordAction = m_pTimerAfterCompleteChoiceCtrl->GetSelection();
954 
955  // Save the options back to the prefs file
956  gPrefs->Write("/TimerRecord/AutoSave", m_bAutoSaveEnabled);
957  gPrefs->Write("/TimerRecord/AutoExport", m_bAutoExportEnabled);
958  gPrefs->Write("/TimerRecord/PostAction", iPostRecordAction);
959 
960  return true;
961 }
962 
963 // Update m_TimeSpan_Duration and ctrl based on m_DateTime_Start and m_DateTime_End.
965 {
967  m_pTimeTextCtrl_Duration->SetValue(m_TimeSpan_Duration.GetSeconds().ToDouble());
968 }
969 
970 // Update m_DateTime_End and ctrls based on m_DateTime_Start and m_TimeSpan_Duration.
972 {
973  //v Use remaining disk -> record time calcs from AudacityProject::OnTimer to set range?
975  //wxLogDebug( "Time start %s end %s",
976  // m_DateTime_Start.FormatISOCombined(' '),
977  // m_DateTime_End.FormatISOCombined(' ') );
978 
979  // Disable the range limitation (to fix Bug 1749 and 1978)
980  // Otherwise SetVallue asserts when going back in time.
981  m_pDatePickerCtrl_End->SetRange(wxInvalidDateTime, wxInvalidDateTime);
983  // Re-enable range limitation to constrain user input.
984  m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
985  m_pDatePickerCtrl_End->Refresh();
987 }
988 
990 {
991  // MY: The Waiting For Start dialog now shows what actions will occur after recording has completed
992  auto sPostAction = Verbatim(
993  m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() );
994 
995  // Two column layout.
997  {
998  XO("Waiting to start recording at:") ,
999  XO("Recording duration:") ,
1000  XO("Scheduled to stop at:") ,
1001  {} ,
1002  XO("Automatic Save enabled:") ,
1003  XO("Automatic Export enabled:") ,
1004  XO("Action after Timer Recording:") ,
1005  },
1006  {
1008  Verbatim( m_TimeSpan_Duration.Format() ),
1010  {} ,
1011  (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) ,
1012  (m_bAutoExportEnabled ? XO("Yes") : XO("No")) ,
1013  sPostAction ,
1014  },
1015  };
1016 
1017  wxDateTime startWait_DateTime = wxDateTime::UNow();
1018  wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime;
1019  TimerProgressDialog progress(waitDuration.GetMilliseconds().GetValue(),
1020  XO("Audacity Timer Record - Waiting for Start"),
1021  columns,
1023  /* i18n-hint: "in" means after a duration of time,
1024  which is shown below this string */
1025  XO("Recording will commence in:"));
1026 
1027  auto updateResult = ProgressResult::Success;
1028  bool bIsRecording = false;
1029  while (updateResult == ProgressResult::Success && !bIsRecording)
1030  {
1031  updateResult = progress.UpdateProgress();
1032  wxMilliSleep(kTimerInterval);
1033  bIsRecording = (m_DateTime_Start <= wxDateTime::UNow());
1034  }
1035  return updateResult;
1036 }
1037 
1039 {
1041  ->GetString(iActionIndex) );
1042 
1043  /* i18n-hint: %s is one of "Do nothing", "Exit Audacity", "Restart system",
1044  or "Shutdown system", and
1045  "in" means after a duration of time, shown below this string */
1046  auto sCountdownLabel = XO("%s in:").Format( sAction );
1047 
1048  // Two column layout.
1050  {
1051  XO("Timer Recording completed.") ,
1052  {} ,
1053  XO("Recording Saved:") ,
1054  XO("Recording Exported:") ,
1055  XO("Action after Timer Recording:") ,
1056  },
1057  {
1058  {} ,
1059  {} ,
1060  ((eCompletedActions & TR_ACTION_SAVED) ? XO("Yes") : XO("No")) ,
1061  ((eCompletedActions & TR_ACTION_EXPORTED) ? XO("Yes") : XO("No")) ,
1062  sAction ,
1063  },
1064  };
1065 
1066 
1067  wxDateTime dtNow = wxDateTime::UNow();
1068  wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
1069  wxDateTime dtActionTime = dtNow.Add(tsWait);
1070 
1071  TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
1072  XO("Audacity Timer Record - Waiting"),
1073  columns,
1075  sCountdownLabel);
1076 
1077  auto iUpdateResult = ProgressResult::Success;
1078  bool bIsTime = false;
1079  while (iUpdateResult == ProgressResult::Success && !bIsTime)
1080  {
1081  iUpdateResult = dlgAction.UpdateProgress();
1082  wxMilliSleep(kTimerInterval);
1083  bIsTime = (dtActionTime <= wxDateTime::UNow());
1084  }
1085  return iUpdateResult;
1086 }
ID_TIMETEXT_END
@ ID_TIMETEXT_END
Definition: TimerRecordDialog.cpp:67
TimerRecordDialog::m_pTimeTextCtrl_Duration
NumericTextCtrl * m_pTimeTextCtrl_Duration
Definition: TimerRecordDialog.h:119
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
TranslatableString
Definition: Types.h:290
TimerRecordDialog::m_timer
wxTimer m_timer
Definition: TimerRecordDialog.h:121
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:36
TimerRecordDialog::m_fnAutoSaveFile
wxFileName m_fnAutoSaveFile
Definition: TimerRecordDialog.h:139
TimerRecordDialog.h
ShuttleGuiBase::AddChoice
wxChoice * AddChoice(const TranslatableString &Prompt, const TranslatableStrings &choices, int Selected=-1)
Definition: ShuttleGui.cpp:391
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1177
TimerRecordDialog::UpdateEnd
void UpdateEnd()
Definition: TimerRecordDialog.cpp:971
ProjectFileIO::GetFileName
const FilePath & GetFileName() const
Definition: ProjectFileIO.cpp:1444
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:302
TimerRecordDialog::OnAutoExportPathButton_Click
void OnAutoExportPathButton_Click(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:339
ProjectFileIO.h
ProjectAudioManager::Get
static ProjectAudioManager & Get(AudacityProject &project)
Definition: ProjectAudioManager.cpp:51
ProjectAudioManager::OnRecord
void OnRecord(bool altAppearance)
Definition: ProjectAudioManager.cpp:465
TimerRecordDialog::m_pTimerAutoExportCheckBoxCtrl
wxCheckBox * m_pTimerAutoExportCheckBoxCtrl
Definition: TimerRecordDialog.h:127
HelpSystem.h
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:67
ID_TIMETEXT_DURATION
@ ID_TIMETEXT_DURATION
Definition: TimerRecordDialog.cpp:68
TimerRecordDialog::OnTimeText_End
void OnTimeText_End(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:269
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
ID_AUTOSAVEPATH_TEXT
@ ID_AUTOSAVEPATH_TEXT
Definition: TimerRecordDialog.cpp:70
TimerProgressDialog::UpdateProgress
ProgressResult UpdateProgress()
Definition: ProgressDialog.cpp:1670
pdlgHideStopButton
@ pdlgHideStopButton
Definition: ProgressDialog.h:43
Exporter
Definition: Export.h:165
TimerRecordDialog::OnHelpButtonClick
void OnHelpButtonClick(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:364
TimerRecordDialog::OnDatePicker_Start
void OnDatePicker_Start(wxDateEvent &event)
Definition: TimerRecordDialog.cpp:205
XO
#define XO(s)
Definition: Internat.h:32
ProgressResult::Cancelled
@ Cancelled
ProjectFileIO::Get
static ProjectFileIO & Get(AudacityProject &project)
Definition: ProjectFileIO.cpp:267
ProgressDialog.h
eCancelButton
@ eCancelButton
Definition: ShuttleGui.h:608
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1212
TimerRecordDialog::m_pTimerExportPathButtonCtrl
wxButton * m_pTimerExportPathButtonCtrl
Definition: TimerRecordDialog.h:129
TimerRecordDialog::OnOK
void OnOK(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:369
ID_AUTOSAVE_CHECKBOX
@ ID_AUTOSAVE_CHECKBOX
Definition: TimerRecordDialog.cpp:73
ProjectAudioManager.h
POST_TIMER_RECORD_CANCEL_WAIT
@ POST_TIMER_RECORD_CANCEL_WAIT
Definition: TimerRecordDialog.h:41
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:964
NumericTextCtrl
Definition: NumericTextCtrl.h:171
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
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:2248
TimerRecordDialog::UpdateTextBoxControls
void UpdateTextBoxControls()
Definition: TimerRecordDialog.cpp:467
TimerRecordDialog::m_bAutoExportEnabled
bool m_bAutoExportEnabled
Definition: TimerRecordDialog.h:140
eOkButton
@ eOkButton
Definition: ShuttleGui.h:607
POST_TIMER_RECORD_CANCEL
@ POST_TIMER_RECORD_CANCEL
Definition: TimerRecordDialog.h:42
pdlgHideElapsedTime
@ pdlgHideElapsedTime
Definition: ProgressDialog.h:45
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:138
wxTextCtrlWrapper
Definition: wxTextCtrlWrapper.h:23
ProgressResult::Failed
@ Failed
XXO
#define XXO(s)
Definition: Internat.h:45
TimerRecordDialog::ExecutePostRecordActions
int ExecutePostRecordActions(bool bWasStopped)
Definition: TimerRecordDialog.cpp:550
ID_DATEPICKER_END
@ ID_DATEPICKER_END
Definition: TimerRecordDialog.cpp:66
kSlowTimerInterval
const int kSlowTimerInterval
Definition: TimerRecordDialog.cpp:84
POST_TIMER_RECORD_CLOSE
@ POST_TIMER_RECORD_CLOSE
Definition: TimerRecordDialog.h:45
TR_ACTION_EXPORTED
@ TR_ACTION_EXPORTED
Definition: TimerRecordDialog.h:36
ProgressResult
ProgressResult
Definition: ProgressDialog.h:33
ProjectFileManager::Get
static ProjectFileManager & Get(AudacityProject &project)
Definition: ProjectFileManager.cpp:56
TimerRecordDialog::NewPathControl
wxTextCtrlWrapper * NewPathControl(wxWindow *wParent, const int iID, const TranslatableString &sCaption, const TranslatableString &sValue)
Definition: TimerRecordDialog.cpp:725
wxTextCtrlWrapper.h
TimerRecordDialog::OnTimeText_Duration
void OnTimeText_Duration(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:289
ProgressResult::Success
@ Success
TimerRecordDialog::m_iAutoExportFilterIndex
int m_iAutoExportFilterIndex
Definition: TimerRecordDialog.h:144
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1203
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1196
eHelpButton
@ eHelpButton
Definition: ShuttleGui.h:611
TimerProgressDialog
Definition: ProgressDialog.h:157
wxDateTime_to_AudacityTime
static double wxDateTime_to_AudacityTime(wxDateTime &dateTime)
Definition: TimerRecordDialog.cpp:89
TimerRecordDialog::WaitForStart
ProgressResult WaitForStart()
Definition: TimerRecordDialog.cpp:989
ProgressDialog::MessageTable
std::vector< MessageColumn > MessageTable
Definition: ProgressDialog.h:67
TimerRecordDialog::m_pTimerSavePathTextCtrl
wxTextCtrlWrapper * m_pTimerSavePathTextCtrl
Definition: TimerRecordDialog.h:125
pdlgConfirmStopCancel
@ pdlgConfirmStopCancel
Definition: ProgressDialog.h:46
TimerRecordDialog::m_pTimerSavePathButtonCtrl
wxButton * m_pTimerSavePathButtonCtrl
Definition: TimerRecordDialog.h:126
NumericConverter::TIME
@ TIME
Definition: NumericTextCtrl.h:51
ProgressResult::Stopped
@ Stopped
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:503
TimerRecordDialog::m_DateTime_Start
wxDateTime m_DateTime_Start
Definition: TimerRecordDialog.h:108
@0::kTimerInterval
@ kTimerInterval
ID_AUTOEXPORTPATH_BUTTON
@ ID_AUTOEXPORTPATH_BUTTON
Definition: TimerRecordDialog.cpp:71
ProjectFileManager.h
TimerRecordDialog::PreActionDelay
ProgressResult PreActionDelay(int iActionIndex, TimerRecordCompletedActions eCompletedActions)
Definition: TimerRecordDialog.cpp:1038
TimerRecordDialog::m_bProjectAlreadySaved
bool m_bProjectAlreadySaved
Definition: TimerRecordDialog.h:145
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
TimerRecordDialog::m_pDatePickerCtrl_Start
wxDatePickerCtrl * m_pDatePickerCtrl_Start
Definition: TimerRecordDialog.h:113
TimerRecordDialog::mProject
AudacityProject & mProject
Definition: TimerRecordDialog.h:106
TimerRecordDialog::m_DateTime_End
wxDateTime m_DateTime_End
Definition: TimerRecordDialog.h:109
ShuttleGui.h
ProjectAudioManager::Stop
void Stop(bool stopStream=true)
Definition: ProjectAudioManager.cpp:309
ID_AUTOSAVEPATH_BUTTON
@ ID_AUTOSAVEPATH_BUTTON
Definition: TimerRecordDialog.cpp:69
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:353
ID_TIMETEXT_START
@ ID_TIMETEXT_START
Definition: TimerRecordDialog.cpp:65
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:886
TimerRecordDialog::OnAutoSaveCheckBox_Change
void OnAutoSaveCheckBox_Change(wxCommandEvent &event)
Definition: TimerRecordDialog.cpp:356
ID_AUTOEXPORT_CHECKBOX
@ ID_AUTOEXPORT_CHECKBOX
Definition: TimerRecordDialog.cpp:74
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
TimerRecordDialog::~TimerRecordDialog
~TimerRecordDialog()
Definition: TimerRecordDialog.cpp:190
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:670
wxDialogWrapper
Definition: wxPanelWrapper.h:81
POST_TIMER_RECORD_NOTHING
@ POST_TIMER_RECORD_NOTHING
Definition: TimerRecordDialog.h:44
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow)
Definition: ShuttleGui.cpp:292
WindowAccessible.h
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:151
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const wxString &localFileName, const wxString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:238
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
_
#define _(s)
Definition: Internat.h:76
TIMER_ID
#define TIMER_ID
Definition: TimerRecordDialog.cpp:61
TimerRecordDialog::m_pTimeTextCtrl_Start
NumericTextCtrl * m_pTimeTextCtrl_Start
Definition: TimerRecordDialog.h:114
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:112
ID_DATEPICKER_START
@ ID_DATEPICKER_START
Definition: TimerRecordDialog.cpp:64
kTimerInterval
const int kTimerInterval
Definition: TimerRecordDialog.cpp:87
TimerRecordCompletedActions
TimerRecordCompletedActions
Definition: TimerRecordDialog.h:33
FileNames.h
Verbatim
TranslatableString Verbatim(wxString str)
Definition: Types.h:581
ErrorDialog.h
wxTextCtrlWrapper::SetReadOnly
void SetReadOnly(bool readonly=true)
Definition: wxTextCtrlWrapper.h:66
AudacityMessageBox.h
TimerRecordDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: TimerRecordDialog.cpp:736
TimerRecordDialog::m_iAutoExportSubFormat
int m_iAutoExportSubFormat
Definition: TimerRecordDialog.h:143
NumericTextCtrl.h
TimerRecordDialog::m_pDatePickerCtrl_End
wxDatePickerCtrl * m_pDatePickerCtrl_End
Definition: TimerRecordDialog.h:116
TimerRecordDialog::m_pTimerAfterCompleteChoiceCtrl
wxChoice * m_pTimerAfterCompleteChoiceCtrl
Definition: TimerRecordDialog.h:132
Track.h
declares abstract base class Track, TrackList, and iterators over TrackList
TimerRecordDialog::m_TimeSpan_Duration
wxTimeSpan m_TimeSpan_Duration
Definition: TimerRecordDialog.h:110
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2406
Prefs.h
TimerRecordDialog::m_fnAutoExportFile
wxFileName m_fnAutoExportFile
Definition: TimerRecordDialog.h:141
ShuttleGuiBase::AddPrompt
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:231
TimerRecordDialog::m_pTimeTextCtrl_End
NumericTextCtrl * m_pTimeTextCtrl_End
Definition: TimerRecordDialog.h:117
TranslatableString::Translation
wxString Translation() const
Definition: Types.h:337
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:497
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:676
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:915
safenew
#define safenew
Definition: MemoryX.h:8
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:195
TimerRecordDialog::m_iAutoExportFormat
int m_iAutoExportFormat
Definition: TimerRecordDialog.h:142
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:128
TimerRecordDialog::m_pTimerAutoSaveCheckBoxCtrl
wxCheckBox * m_pTimerAutoSaveCheckBoxCtrl
Definition: TimerRecordDialog.h:124
pdlgHideCancelButton
@ pdlgHideCancelButton
Definition: ProgressDialog.h:44
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:638
CONTROL_GROUP_SAVE
@ CONTROL_GROUP_SAVE
Definition: TimerRecordDialog.cpp:78
ID_AUTOEXPORTPATH_TEXT
@ ID_AUTOEXPORTPATH_TEXT
Definition: TimerRecordDialog.cpp:72
TimerRecordDialog::TransferDataFromWindow
bool TransferDataFromWindow() override
Definition: TimerRecordDialog.cpp:921