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