Audacity  3.0.3
ProjectManager.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 ProjectManager.cpp
6 
7 Paul Licameli split from AudacityProject.cpp
8 
9 **********************************************************************/
10 
11 #include "ProjectManager.h"
12 
13 
14 
15 #include "ActiveProject.h"
16 #include "AdornedRulerPanel.h"
17 #include "AudioIO.h"
18 #include "Clipboard.h"
19 #include "FileNames.h"
20 #include "Menus.h"
21 #include "ModuleManager.h"
22 #include "Project.h"
23 #include "ProjectAudioIO.h"
24 #include "ProjectAudioManager.h"
25 #include "ProjectFileIO.h"
26 #include "ProjectFileManager.h"
27 #include "ProjectHistory.h"
29 #include "ProjectWindows.h"
30 #include "ProjectRate.h"
31 #include "ProjectSettings.h"
32 #include "ProjectStatus.h"
33 #include "ProjectWindow.h"
34 #include "SelectUtilities.h"
35 #include "TrackPanel.h"
36 #include "TrackUtilities.h"
37 #include "UndoManager.h"
38 #include "WaveTrack.h"
39 #include "wxFileNameWrapper.h"
40 #include "import/Import.h"
41 #include "import/ImportMIDI.h"
42 #include "QualitySettings.h"
43 #include "toolbars/MixerToolBar.h"
44 #include "toolbars/SelectionBar.h"
46 #include "toolbars/TimeToolBar.h"
47 #include "toolbars/ToolManager.h"
49 #include "widgets/FileHistory.h"
51 
52 #include <wx/app.h>
53 #include <wx/dataobj.h>
54 #include <wx/dnd.h>
55 #include <wx/scrolbar.h>
56 #include <wx/sizer.h>
57 
58 #ifdef __WXGTK__
59 #include "../images/AudacityLogoAlpha.xpm"
60 #endif
61 
62 const int AudacityProjectTimerID = 5200;
63 
65  []( AudacityProject &project ) {
66  return std::make_shared< ProjectManager >( project );
67  }
68 };
69 
71 {
72  return project.AttachedObjects::Get< ProjectManager >( sProjectManagerKey );
73 }
74 
76 {
77  return Get( const_cast< AudacityProject & >( project ) );
78 }
79 
81  : mProject{ project }
82  , mTimer{ std::make_unique<wxTimer>(this, AudacityProjectTimerID) }
83 {
84  auto &window = ProjectWindow::Get( mProject );
85  window.Bind( wxEVT_CLOSE_WINDOW, &ProjectManager::OnCloseWindow, this );
86  mProject.Bind(EVT_PROJECT_STATUS_UPDATE,
88  project.Bind( EVT_RECONNECTION_FAILURE,
90 }
91 
93 
94 // PRL: This event type definition used to be in AudacityApp.h, which created
95 // a bad compilation dependency. The event was never emitted anywhere. I
96 // preserve it and its handler here but I move it to remove the dependency.
97 // Asynchronous open
98 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
99  EVT_OPEN_AUDIO_FILE, wxCommandEvent);
100 wxDEFINE_EVENT(EVT_OPEN_AUDIO_FILE, wxCommandEvent);
101 
102 BEGIN_EVENT_TABLE( ProjectManager, wxEvtHandler )
103  EVT_COMMAND(wxID_ANY, EVT_OPEN_AUDIO_FILE, ProjectManager::OnOpenAudioFile)
106 
107 bool ProjectManager::sbWindowRectAlreadySaved = false;
108 bool ProjectManager::sbSkipPromptingForSave = false;
109 
110 void ProjectManager::SaveWindowSize()
111 {
112  if (sbWindowRectAlreadySaved)
113  {
114  return;
115  }
116  bool validWindowForSaveWindowSize = FALSE;
117  ProjectWindow * validProject = nullptr;
118  bool foundIconizedProject = FALSE;
119  for ( auto pProject : AllProjects{} )
120  {
121  auto &window = ProjectWindow::Get( *pProject );
122  if (!window.IsIconized()) {
123  validWindowForSaveWindowSize = TRUE;
124  validProject = &window;
125  break;
126  }
127  else
128  foundIconizedProject = TRUE;
129 
130  }
131  if (validWindowForSaveWindowSize)
132  {
133  wxRect windowRect = validProject->GetRect();
134  wxRect normalRect = validProject->GetNormalizedWindowState();
135  bool wndMaximized = validProject->IsMaximized();
136  gPrefs->Write(wxT("/Window/X"), windowRect.GetX());
137  gPrefs->Write(wxT("/Window/Y"), windowRect.GetY());
138  gPrefs->Write(wxT("/Window/Width"), windowRect.GetWidth());
139  gPrefs->Write(wxT("/Window/Height"), windowRect.GetHeight());
140  gPrefs->Write(wxT("/Window/Maximized"), wndMaximized);
141  gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX());
142  gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY());
143  gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth());
144  gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight());
145  gPrefs->Write(wxT("/Window/Iconized"), FALSE);
146  }
147  else
148  {
149  if (foundIconizedProject) {
150  validProject = &ProjectWindow::Get( **AllProjects{}.begin() );
151  bool wndMaximized = validProject->IsMaximized();
152  wxRect normalRect = validProject->GetNormalizedWindowState();
153  // store only the normal rectangle because the itemized rectangle
154  // makes no sense for an opening project window
155  gPrefs->Write(wxT("/Window/X"), normalRect.GetX());
156  gPrefs->Write(wxT("/Window/Y"), normalRect.GetY());
157  gPrefs->Write(wxT("/Window/Width"), normalRect.GetWidth());
158  gPrefs->Write(wxT("/Window/Height"), normalRect.GetHeight());
159  gPrefs->Write(wxT("/Window/Maximized"), wndMaximized);
160  gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX());
161  gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY());
162  gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth());
163  gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight());
164  gPrefs->Write(wxT("/Window/Iconized"), TRUE);
165  }
166  else {
167  // this would be a very strange case that might possibly occur on the Mac
168  // Audacity would have to be running with no projects open
169  // in this case we are going to write only the default values
170  wxRect defWndRect;
171  GetDefaultWindowRect(&defWndRect);
172  gPrefs->Write(wxT("/Window/X"), defWndRect.GetX());
173  gPrefs->Write(wxT("/Window/Y"), defWndRect.GetY());
174  gPrefs->Write(wxT("/Window/Width"), defWndRect.GetWidth());
175  gPrefs->Write(wxT("/Window/Height"), defWndRect.GetHeight());
176  gPrefs->Write(wxT("/Window/Maximized"), FALSE);
177  gPrefs->Write(wxT("/Window/Normal_X"), defWndRect.GetX());
178  gPrefs->Write(wxT("/Window/Normal_Y"), defWndRect.GetY());
179  gPrefs->Write(wxT("/Window/Normal_Width"), defWndRect.GetWidth());
180  gPrefs->Write(wxT("/Window/Normal_Height"), defWndRect.GetHeight());
181  gPrefs->Write(wxT("/Window/Iconized"), FALSE);
182  }
183  }
184  gPrefs->Flush();
185  sbWindowRectAlreadySaved = true;
186 }
187 
188 #if wxUSE_DRAG_AND_DROP
189 class FileObject final : public wxFileDataObject
190 {
191 public:
192  FileObject()
193  {
194  }
195 
196  bool IsSupportedFormat(const wxDataFormat & format, Direction WXUNUSED(dir = Get)) const
197  // PRL: This function does NOT override any inherited virtual! What does it do?
198  {
199  if (format.GetType() == wxDF_FILENAME) {
200  return true;
201  }
202 
203 #if defined(__WXMAC__)
204 #if !wxCHECK_VERSION(3, 0, 0)
205  if (format.GetFormatId() == kDragPromisedFlavorFindFile) {
206  return true;
207  }
208 #endif
209 #endif
210 
211  return false;
212  }
213 };
214 
215 class DropTarget final : public wxFileDropTarget
216 {
217 public:
218  DropTarget(AudacityProject *proj)
219  {
220  mProject = proj;
221 
222  // SetDataObject takes ownership
223  SetDataObject(safenew FileObject());
224  }
225 
226  ~DropTarget()
227  {
228  }
229 
230 #if defined(__WXMAC__)
231 #if !wxCHECK_VERSION(3, 0, 0)
232  bool GetData() override
233  {
234  bool foundSupported = false;
235  bool firstFileAdded = false;
236  OSErr result;
237 
238  UInt16 items = 0;
239  CountDragItems((DragReference)m_currentDrag, &items);
240 
241  for (UInt16 index = 1; index <= items; index++) {
242 
243  DragItemRef theItem = 0;
244  GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
245 
246  UInt16 flavors = 0;
247  CountDragItemFlavors((DragReference)m_currentDrag, theItem , &flavors ) ;
248 
249  for (UInt16 flavor = 1 ;flavor <= flavors; flavor++) {
250 
251  FlavorType theType = 0;
252  result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor, &theType);
253  if (theType != kDragPromisedFlavorFindFile && theType != kDragFlavorTypeHFS) {
254  continue;
255  }
256  foundSupported = true;
257 
258  Size dataSize = 0;
259  GetFlavorDataSize((DragReference)m_currentDrag, theItem, theType, &dataSize);
260 
261  ArrayOf<char> theData{ dataSize };
262  GetFlavorData((DragReference)m_currentDrag, theItem, theType, (void*) theData.get(), &dataSize, 0L);
263 
264  wxString name;
265  if (theType == kDragPromisedFlavorFindFile) {
266  name = wxMacFSSpec2MacFilename((FSSpec *)theData.get());
267  }
268  else if (theType == kDragFlavorTypeHFS) {
269  name = wxMacFSSpec2MacFilename(&((HFSFlavor *)theData.get())->fileSpec);
270  }
271 
272  if (!firstFileAdded) {
273  // reset file list
274  ((wxFileDataObject*)GetDataObject())->SetData(0, "");
275  firstFileAdded = true;
276  }
277 
278  ((wxFileDataObject*)GetDataObject())->AddFile(name);
279 
280  // We only want to process one flavor
281  break;
282  }
283  }
284  return foundSupported;
285  }
286 #endif
287 
288  bool OnDrop(wxCoord x, wxCoord y) override
289  {
290  // bool foundSupported = false;
291 #if !wxCHECK_VERSION(3, 0, 0)
292  bool firstFileAdded = false;
293  OSErr result;
294 
295  UInt16 items = 0;
296  CountDragItems((DragReference)m_currentDrag, &items);
297 
298  for (UInt16 index = 1; index <= items; index++) {
299 
300  DragItemRef theItem = 0;
301  GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
302 
303  UInt16 flavors = 0;
304  CountDragItemFlavors((DragReference)m_currentDrag, theItem , &flavors ) ;
305 
306  for (UInt16 flavor = 1 ;flavor <= flavors; flavor++) {
307 
308  FlavorType theType = 0;
309  result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor, &theType);
310  if (theType != kDragPromisedFlavorFindFile && theType != kDragFlavorTypeHFS) {
311  continue;
312  }
313  return true;
314  }
315  }
316 #endif
317  return CurrentDragHasSupportedFormat();
318  }
319 
320 #endif
321 
322  bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString& filenames) override
323  {
324  // Experiment shows that this function can be reached while there is no
325  // catch block above in wxWidgets. So stop all exceptions here.
326  return GuardedCall< bool > ( [&] {
327  wxArrayString sortednames(filenames);
328  sortednames.Sort(FileNames::CompareNoCase);
329 
330  auto cleanup = finally( [&] {
331  ProjectWindow::Get( *mProject ).HandleResize(); // Adjust scrollers for NEW track sizes.
332  } );
333 
334  for (const auto &name : sortednames) {
335 #ifdef USE_MIDI
336  if (FileNames::IsMidi(name))
337  DoImportMIDI( *mProject, name );
338  else
339 #endif
340  ProjectFileManager::Get( *mProject ).Import(name);
341  }
342 
343  auto &window = ProjectWindow::Get( *mProject );
344  window.ZoomAfterImport(nullptr);
345 
346  return true;
347  } );
348  }
349 
350 private:
351  AudacityProject *mProject;
352 };
353 
354 #endif
355 
356 #ifdef EXPERIMENTAL_NOTEBOOK
357  extern void AddPages( AudacityProject * pProj, GuiFactory & Factory, wxNotebook * pNotebook );
358 #endif
359 
361 {
362  auto &project = window.GetProject();
363 
364 #ifdef EXPERIMENTAL_DA2
365  SetBackgroundColour(theTheme.Colour( clrMedium ));
366 #endif
367  // Note that the first field of the status bar is a dummy, and its width is set
368  // to zero latter in the code. This field is needed for wxWidgets 2.8.12 because
369  // if you move to the menu bar, the first field of the menu bar is cleared, which
370  // is undesirable behaviour.
371  // In addition, the help strings of menu items are by default sent to the first
372  // field. Currently there are no such help strings, but it they were introduced, then
373  // there would need to be an event handler to send them to the appropriate field.
374  auto statusBar = window.CreateStatusBar(4);
375 #if wxUSE_ACCESSIBILITY
376  // so that name can be set on a standard control
377  statusBar->SetAccessible(safenew WindowAccessible(statusBar));
378 #endif
379  statusBar->SetName(wxT("status_line")); // not localized
380 
381  auto &viewInfo = ViewInfo::Get( project );
382 
383  // LLL: Read this!!!
384  //
385  // Until the time (and cpu) required to refresh the track panel is
386  // reduced, leave the following window creations in the order specified.
387  // This will place the refresh of the track panel last, allowing all
388  // the others to get done quickly.
389  //
390  // Near as I can tell, this is only a problem under Windows.
391  //
392 
393 
394  //
395  // Create the ToolDock
396  //
397  ToolManager::Get( project ).CreateWindows();
398  ToolManager::Get( project ).LayoutToolBars();
399 
400  //
401  // Create the horizontal ruler
402  //
403  auto &ruler = AdornedRulerPanel::Get( project );
404 
405  //
406  // Create the TrackPanel and the scrollbars
407  //
408 
409  auto topPanel = window.GetTopPanel();
410 
411  {
412  auto ubs = std::make_unique<wxBoxSizer>(wxVERTICAL);
413  ubs->Add( ToolManager::Get( project ).GetTopDock(), 0, wxEXPAND | wxALIGN_TOP );
414  ubs->Add(&ruler, 0, wxEXPAND);
415  topPanel->SetSizer(ubs.release());
416  }
417 
418  // Ensure that the topdock comes before the ruler in the tab order,
419  // irrespective of the order in which they were created.
420  ToolManager::Get(project).GetTopDock()->MoveBeforeInTabOrder(&ruler);
421 
422  const auto pPage = window.GetMainPage();
423 
424  wxBoxSizer *bs;
425  {
426  auto ubs = std::make_unique<wxBoxSizer>(wxVERTICAL);
427  bs = ubs.get();
428  bs->Add(topPanel, 0, wxEXPAND | wxALIGN_TOP);
429  bs->Add(pPage, 1, wxEXPAND);
430  bs->Add( ToolManager::Get( project ).GetBotDock(), 0, wxEXPAND );
431  window.SetAutoLayout(true);
432  window.SetSizer(ubs.release());
433  }
434  bs->Layout();
435 
436  auto &trackPanel = TrackPanel::Get( project );
437 
438  // LLL: When Audacity starts or becomes active after returning from
439  // another application, the first window that can accept focus
440  // will be given the focus even if we try to SetFocus(). By
441  // making the TrackPanel that first window, we resolve several
442  // keyboard focus problems.
443  pPage->MoveBeforeInTabOrder(topPanel);
444 
445  bs = (wxBoxSizer *)pPage->GetSizer();
446 
447  auto vsBar = &window.GetVerticalScrollBar();
448  auto hsBar = &window.GetHorizontalScrollBar();
449 
450  {
451  // Top horizontal grouping
452  auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
453 
454  // Track panel
455  hs->Add(&trackPanel, 1, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP);
456 
457  {
458  // Vertical grouping
459  auto vs = std::make_unique<wxBoxSizer>(wxVERTICAL);
460 
461  // Vertical scroll bar
462  vs->Add(vsBar, 1, wxEXPAND | wxALIGN_TOP);
463  hs->Add(vs.release(), 0, wxEXPAND | wxALIGN_TOP);
464  }
465 
466  bs->Add(hs.release(), 1, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP);
467  }
468 
469  {
470  // Bottom horizontal grouping
471  auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
472 
473  // Bottom scrollbar
474  hs->Add(viewInfo.GetLeftOffset() - 1, 0);
475  hs->Add(hsBar, 1, wxALIGN_BOTTOM);
476  hs->Add(vsBar->GetSize().GetWidth(), 0);
477  bs->Add(hs.release(), 0, wxEXPAND | wxALIGN_LEFT);
478  }
479 
480  // Lay it out
481  pPage->SetAutoLayout(true);
482  pPage->Layout();
483 
484 #ifdef EXPERIMENTAL_NOTEBOOK
485  AddPages(this, Factory, pNotebook);
486 #endif
487 
488  auto mainPanel = window.GetMainPanel();
489 
490  mainPanel->Layout();
491 
492  wxASSERT( trackPanel.GetProject() == &project );
493 
494  // MM: Give track panel the focus to ensure keyboard commands work
495  trackPanel.SetFocus();
496 
497  window.FixScrollbars();
498  ruler.SetLeftOffset(viewInfo.GetLeftOffset()); // bevel on AdornedRuler
499 
500  //
501  // Set the Icon
502  //
503 
504  // loads either the XPM or the windows resource, depending on the platform
505 #if !defined(__WXMAC__) && !defined(__WXX11__)
506  {
507 #if defined(__WXMSW__)
508  wxIcon ic{ wxICON(AudacityLogo) };
509 #elif defined(__WXGTK__)
510  wxIcon ic{wxICON(AudacityLogoAlpha)};
511 #else
512  wxIcon ic{};
513  ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
514 #endif
515  window.SetIcon(ic);
516  }
517 #endif
518 
519  window.UpdateStatusWidths();
520  auto msg = XO("Welcome to Audacity version %s")
521  .Format( AUDACITY_VERSION_STRING );
523 
524 #ifdef EXPERIMENTAL_DA2
525  ClearBackground();// For wxGTK.
526 #endif
527 }
528 
530 {
531  wxRect wndRect;
532  bool bMaximized = false;
533  bool bIconized = false;
534  GetNextWindowPlacement(&wndRect, &bMaximized, &bIconized);
535 
536  // Create and show a NEW project
537  // Use a non-default deleter in the smart pointer!
538  auto sp = std::make_shared< AudacityProject >();
539  AllProjects{}.Add( sp );
540  auto p = sp.get();
541  auto &project = *p;
542  auto &projectHistory = ProjectHistory::Get( project );
543  auto &projectManager = Get( project );
544  auto &window = ProjectWindow::Get( *p );
545  InitProjectWindow( window );
546 
547  // wxGTK3 seems to need to require creating the window using default position
548  // and then manually positioning it.
549  window.SetPosition(wndRect.GetPosition());
550 
551  auto &projectFileManager = ProjectFileManager::Get( *p );
552 
553  // This may report an error.
554  projectFileManager.OpenNewProject();
555 
556  MenuManager::Get( project ).CreateMenusAndCommands( project );
557 
558  projectHistory.InitialState();
559  projectManager.RestartTimer();
560 
561  if(bMaximized) {
562  window.Maximize(true);
563  }
564  else if (bIconized) {
565  // if the user close down and iconized state we could start back up and iconized state
566  // window.Iconize(TRUE);
567  }
568 
569  //Initialise the Listeners
570  auto gAudioIO = AudioIO::Get();
571  gAudioIO->SetListener(
572  ProjectAudioManager::Get( project ).shared_from_this() );
573  auto &projectSelectionManager = ProjectSelectionManager::Get( project );
574  SelectionBar::Get( project ).SetListener( &projectSelectionManager );
575 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
576  SpectralSelectionBar::Get( project ).SetListener( &projectSelectionManager );
577 #endif
578  TimeToolBar::Get( project ).SetListener( &projectSelectionManager );
579 
580 #if wxUSE_DRAG_AND_DROP
581  // We can import now, so become a drag target
582  // SetDropTarget(safenew AudacityDropTarget(this));
583  // mTrackPanel->SetDropTarget(safenew AudacityDropTarget(this));
584 
585  // SetDropTarget takes ownership
586  TrackPanel::Get( project ).SetDropTarget( safenew DropTarget( &project ) );
587 #endif
588 
589  //Set the NEW project as active:
590  SetActiveProject(p);
591 
592  // Okay, GetActiveProject() is ready. Now we can get its CommandManager,
593  // and add the shortcut keys to the tooltips.
595 
597 
598  window.Show(true);
599 
600  return p;
601 }
602 
603 void ProjectManager::OnReconnectionFailure(wxCommandEvent & event)
604 {
605  event.Skip();
606  wxTheApp->CallAfter([this]{
607  ProjectWindow::Get(mProject).Close(true);
608  });
609 }
610 
611 static bool sbClosingAll = false;
612 
614 {
615  sbClosingAll = closing;
616 }
617 
618 void ProjectManager::OnCloseWindow(wxCloseEvent & event)
619 {
620  auto &project = mProject;
621  auto &projectFileIO = ProjectFileIO::Get( project );
622  auto &projectFileManager = ProjectFileManager::Get( project );
623  const auto &settings = ProjectSettings::Get( project );
624  auto &projectAudioIO = ProjectAudioIO::Get( project );
625  auto &tracks = TrackList::Get( project );
626  auto &window = ProjectWindow::Get( project );
627  auto gAudioIO = AudioIO::Get();
628 
629  // We are called for the wxEVT_CLOSE_WINDOW, wxEVT_END_SESSION, and
630  // wxEVT_QUERY_END_SESSION, so we have to protect against multiple
631  // entries. This is a hack until the whole application termination
632  // process can be reviewed and reworked. (See bug #964 for ways
633  // to exercise the bug that instigated this hack.)
634  if (window.IsBeingDeleted())
635  {
636  event.Skip();
637  return;
638  }
639 
640  if (event.CanVeto() && (::wxIsBusy() || project.mbBusyImporting))
641  {
642  event.Veto();
643  return;
644  }
645 
646  // Check to see if we were playing or recording
647  // audio, and if so, make sure Audio I/O is completely finished.
648  // The main point of this is to properly push the state
649  // and flush the tracks once we've completely finished
650  // recording NEW state.
651  // This code is derived from similar code in
652  // AudacityProject::~AudacityProject() and TrackPanel::OnTimer().
653  if (projectAudioIO.GetAudioIOToken()>0 &&
654  gAudioIO->IsStreamActive(projectAudioIO.GetAudioIOToken())) {
655 
656  // We were playing or recording audio, but we've stopped the stream.
657  ProjectAudioManager::Get( project ).Stop();
658 
659  projectAudioIO.SetAudioIOToken(0);
660  window.RedrawProject();
661  }
662  else if (gAudioIO->IsMonitoring()) {
663  gAudioIO->StopStream();
664  }
665 
666  // MY: Use routine here so other processes can make same check
667  bool bHasTracks = !tracks.empty();
668 
669  // We may not bother to prompt the user to save, if the
670  // project is now empty.
672  && event.CanVeto()
673  && (settings.EmptyCanBeDirty() || bHasTracks)) {
674  if ( UndoManager::Get( project ).UnsavedChanges() ) {
675  TitleRestorer Restorer( window, project );// RAII
676  /* i18n-hint: The first %s numbers the project, the second %s is the project name.*/
677  auto Title = XO("%sSave changes to %s?")
678  .Format( Restorer.sProjNumber, Restorer.sProjName );
679  auto Message = XO("Save project before closing?");
680  if( !bHasTracks )
681  {
682  Message += XO("\nIf saved, the project will have no tracks.\n\nTo save any previously open tracks:\nCancel, Edit > Undo until all tracks\nare open, then File > Save Project.");
683  }
684  int result = AudacityMessageBox(
685  Message,
686  Title,
687  wxYES_NO | wxCANCEL | wxICON_QUESTION,
688  &window);
689 
690  if (result == wxCANCEL || (result == wxYES &&
691  !GuardedCall<bool>( [&]{ return projectFileManager.Save(); } )
692  )) {
693  event.Veto();
694  return;
695  }
696  }
697  }
698 #ifdef __WXMAC__
699  // Fix bug apparently introduced into 2.1.2 because of wxWidgets 3:
700  // closing a project that was made full-screen (as by clicking the green dot
701  // or command+/; not merely "maximized" as by clicking the title bar or
702  // Zoom in the Window menu) leaves the screen black.
703  // Fix it by un-full-screening.
704  // (But is there a different way to do this? What do other applications do?
705  // I don't see full screen windows of Safari shrinking, but I do see
706  // momentary blackness.)
707  window.ShowFullScreen(false);
708 #endif
709 
711 
712  // Stop the timer since there's no need to update anything anymore
713  mTimer.reset();
714 
715  // DMM: Save the size of the last window the user closes
716  //
717  // LL: Save before doing anything else to the window that might make
718  // its size change.
719  SaveWindowSize();
720 
721  window.SetIsBeingDeleted();
722 
723  // Mac: we never quit as the result of a close.
724  // Other systems: we quit only when the close is the result of an external
725  // command (on Windows, those are taskbar closes, "X" box, Alt+F4, etc.)
726  bool quitOnClose;
727 #ifdef __WXMAC__
728  quitOnClose = false;
729 #else
730  quitOnClose = !projectFileManager.GetMenuClose();
731 #endif
732 
733  // DanH: If we're definitely about to quit, clear the clipboard.
734  auto &clipboard = Clipboard::Get();
735  if ((AllProjects{}.size() == 1) &&
736  (quitOnClose || sbClosingAll))
737  clipboard.Clear();
738  else {
739  auto clipboardProject = clipboard.Project().lock();
740  if ( clipboardProject.get() == &mProject ) {
741  // Closing the project from which content was cut or copied.
742  // For 3.0.0, clear the clipboard, because accessing clipboard contents
743  // would depend on a database connection to the closing project, but
744  // that connection should closed now so that the project file can be
745  // freely moved.
746  // Notes:
747  // 1) maybe clipboard contents could be saved by migrating them to
748  // another temporary database, but that extra effort is beyond the
749  // scope of 3.0.0.
750  // 2) strictly speaking this is necessary only when the clipboard
751  // contains WaveTracks.
752  clipboard.Clear();
753  }
754  }
755 
756  // JKC: For Win98 and Linux do not detach the menu bar.
757  // We want wxWidgets to clean it up for us.
758  // TODO: Is there a Mac issue here??
759  // SetMenuBar(NULL);
760 
761  // Compact the project.
762  projectFileManager.CompactProjectOnClose();
763 
764  // Set (or not) the bypass flag to indicate that deletes that would happen during
765  // the UndoManager::ClearStates() below are not necessary.
766  projectFileIO.SetBypass();
767 
768  {
769  // This can reduce reference counts of sample blocks in the project's
770  // tracks.
771  UndoManager::Get( project ).ClearStates();
772 
773  // Delete all the tracks to free up memory
774  tracks.Clear();
775  }
776 
777  // Some of the AdornedRulerPanel functions refer to the TrackPanel, so destroy this
778  // before the TrackPanel is destroyed. This change was needed to stop Audacity
779  // crashing when running with Jaws on Windows 10 1703.
780  AdornedRulerPanel::Destroy( project );
781 
782  // Destroy the TrackPanel early so it's not around once we start
783  // deleting things like tracks and such out from underneath it.
784  // Check validity of mTrackPanel per bug 584 Comment 1.
785  // Deeper fix is in the Import code, but this failsafes against crash.
786  TrackPanel::Destroy( project );
787  // Finalize the tool manager before the children since it needs
788  // to save the state of the toolbars.
789  ToolManager::Get( project ).Destroy();
790 
791  window.DestroyChildren();
792 
793  // Close project only now, because TrackPanel might have been holding
794  // some shared_ptr to WaveTracks keeping SampleBlocks alive.
795  // We're all done with the project file, so close it now
796  projectFileManager.CloseProject();
797 
798  WaveTrackFactory::Destroy( project );
799 
800  // Remove self from the global array, but defer destruction of self
801  auto pSelf = AllProjects{}.Remove( project );
802  wxASSERT( pSelf );
803 
804  if (GetActiveProject().lock().get() == &project) {
805  // Find a NEW active project
806  if ( !AllProjects{}.empty() ) {
807  SetActiveProject(AllProjects{}.begin()->get());
808  }
809  else {
810  SetActiveProject(nullptr);
811  }
812  }
813 
814  // Since we're going to be destroyed, make sure we're not to
815  // receive audio notifications anymore.
816  // PRL: Maybe all this is unnecessary now that the listener is managed
817  // by a weak pointer.
818  if ( gAudioIO->GetListener().get() == &ProjectAudioManager::Get( project ) ) {
819  auto active = GetActiveProject().lock();
820  gAudioIO->SetListener(
821  active
822  ? ProjectAudioManager::Get( *active ).shared_from_this()
823  : nullptr
824  );
825  }
826 
827  if (AllProjects{}.empty() && !sbClosingAll) {
828 
829 #if !defined(__WXMAC__)
830  if (quitOnClose) {
831  // Simulate the application Exit menu item
832  wxCommandEvent evt{ wxEVT_MENU, wxID_EXIT };
833  wxTheApp->AddPendingEvent( evt );
834  }
835  else {
836  sbWindowRectAlreadySaved = false;
837  // For non-Mac, always keep at least one project window open
838  (void) New();
839  }
840 #endif
841  }
842 
843  window.Destroy();
844 
845  // Destroys this
846  pSelf.reset();
847 }
848 
849 // PRL: I preserve this handler function for an event that was never sent, but
850 // I don't know the intention.
851 void ProjectManager::OnOpenAudioFile(wxCommandEvent & event)
852 {
853  const wxString &cmd = event.GetString();
854  if (!cmd.empty()) {
855  ProjectChooser chooser{ &mProject, true };
856  if (auto project = ProjectFileManager::OpenFile(
857  std::ref(chooser), cmd)) {
858  auto &window = GetProjectFrame( *project );
859  window.RequestUserAttention();
860  chooser.Commit();
861  }
862  }
863 }
864 
865 // static method, can be called outside of a project
867 {
868  auto selectedFiles =
869  ProjectFileManager::ShowOpenDialog(FileNames::Operation::Open);
870  if (selectedFiles.size() == 0) {
872  return;
873  }
874 
875  //first sort selectedFiles.
876  selectedFiles.Sort(FileNames::CompareNoCase);
877 
878  auto cleanup = finally( [] {
880  } );
881 
882  for (const auto &fileName : selectedFiles) {
883  // Make sure it isn't already open.
884  if (ProjectFileManager::IsAlreadyOpen(fileName))
885  continue; // Skip ones that are already open.
886 
887  proj = OpenProject( proj, fileName,
888  true /* addtohistory */, false /* reuseNonemptyProject */ );
889  }
890 }
891 
893 {
894  // DMM: If the project is dirty, that means it's been touched at
895  // all, and it's not safe to open a fresh project directly in its
896  // place. Only if the project is brandnew clean and the user
897  // hasn't done any action at all is it safe for Open to take place
898  // inside the current project.
899  //
900  // If you try to Open a fresh project inside the current window when
901  // there are no tracks, but there's an Undo history, etc, then
902  // bad things can happen, including orphan blocks, or tracks
903  // referring to non-existent blocks
904  if (
905  ProjectHistory::Get( proj ).GetDirty() ||
906  !TrackList::Get( proj ).empty()
907  )
908  return false;
909  // This project is clean; it's never been touched. Therefore
910  // all relevant member variables are in their initial state,
911  // and it's okay to open a NEW project inside its window.
912  return true;
913 }
914 
916 {
917  if (mpUsedProject) {
918  if (mpUsedProject == mpGivenProject) {
919  // Ensure that it happens here: don't wait for the application level
920  // exception handler, because the exception may be intercepted
921  ProjectHistory::Get(*mpGivenProject).RollbackState();
922  // Any exception now continues propagating
923  }
924  else
925  GetProjectFrame( *mpUsedProject ).Close(true);
926  }
927 }
928 
931 {
932  if (mpGivenProject) {
933  // Always check before opening a project file (for safety);
934  // May check even when opening other files
935  // (to preserve old behavior; as with the File > Open command specifying
936  // multiple files of whatever types, so that each gets its own window)
937  bool checkReuse = (openingProjectFile || !mReuseNonemptyProject);
938  if (!checkReuse || SafeToOpenProjectInto(*mpGivenProject))
939  return *(mpUsedProject = mpGivenProject);
940  }
941  return *(mpUsedProject = New());
942 }
943 
945 {
946  mpUsedProject = nullptr;
947 }
948 
950  AudacityProject *pGivenProject, const FilePath &fileNameArg,
951  bool addtohistory, bool reuseNonemptyProject)
952 {
953  ProjectManager::ProjectChooser chooser{ pGivenProject, reuseNonemptyProject };
954  if (auto pProject = ProjectFileManager::OpenFile(
955  std::ref(chooser), fileNameArg, addtohistory )) {
956  chooser.Commit();
957 
958  auto &projectFileIO = ProjectFileIO::Get( *pProject );
959  if( projectFileIO.IsRecovered() ) {
960  auto &window = ProjectWindow::Get( *pProject );
961  window.Zoom( window.GetZoomOfToFit() );
962  // "Project was recovered" replaces "Create new project" in Undo History.
963  auto &undoManager = UndoManager::Get( *pProject );
964  undoManager.RemoveStates(0, 1);
965  }
966  return pProject;
967  }
968  return nullptr;
969 }
970 
971 // This is done to empty out the tracks, but without creating a new project.
973  auto &project = mProject;
974  auto &projectFileIO = ProjectFileIO::Get( project );
975  auto &projectFileManager = ProjectFileManager::Get( project );
976  auto &projectHistory = ProjectHistory::Get( project );
977  auto &viewInfo = ViewInfo::Get( project );
978 
979  SelectUtilities::DoSelectAll( project );
981 
982  WaveTrackFactory::Reset( project );
983 
984  projectHistory.SetDirty( false );
985  auto &undoManager = UndoManager::Get( project );
986  undoManager.ClearStates();
987 
988  projectFileManager.CloseProject();
989  projectFileManager.OpenProject();
990 }
991 
993 {
994  if (mTimer) {
995  // mTimer->Stop(); // not really needed
996  mTimer->Start( 3000 ); // Update messages as needed once every 3 s.
997  }
998 }
999 
1000 void ProjectManager::OnTimer(wxTimerEvent& WXUNUSED(event))
1001 {
1002  auto &project = mProject;
1003  auto &projectAudioIO = ProjectAudioIO::Get( project );
1004  auto mixerToolBar = &MixerToolBar::Get( project );
1005  mixerToolBar->UpdateControls();
1006 
1007  auto gAudioIO = AudioIO::Get();
1008  // gAudioIO->GetNumCaptureChannels() should only be positive
1009  // when we are recording.
1010  if (projectAudioIO.GetAudioIOToken() > 0 && gAudioIO->GetNumCaptureChannels() > 0) {
1011  wxLongLong freeSpace = ProjectFileIO::Get(project).GetFreeDiskSpace();
1012  if (freeSpace >= 0) {
1013 
1014  int iRecordingMins = GetEstimatedRecordingMinsLeftOnDisk(gAudioIO->GetNumCaptureChannels());
1015  auto sMessage = XO("Disk space remaining for recording: %s")
1016  .Format( GetHoursMinsString(iRecordingMins) );
1017 
1018  // Do not change mLastMainStatusMessage
1019  SetStatusText(sMessage, mainStatusBarField);
1020  }
1021  }
1022 
1023  // As also with the TrackPanel timer: wxTimer may be unreliable without
1024  // some restarts
1025  RestartTimer();
1026 }
1027 
1029 {
1030  evt.Skip();
1031 
1032  auto &project = mProject;
1033 
1034  // Be careful to null-check the window. We might get to this function
1035  // during shut-down, but a timer hasn't been told to stop sending its
1036  // messages yet.
1037  auto pWindow = ProjectWindow::Find( &project );
1038  if ( !pWindow )
1039  return;
1040  auto &window = *pWindow;
1041 
1042  window.UpdateStatusWidths();
1043 
1044  auto field = evt.mField;
1045  const auto &msg = ProjectStatus::Get( project ).Get( field );
1046  SetStatusText( msg, field );
1047 
1048  if ( field == mainStatusBarField )
1049  // When recording, let the NEW status message stay at least as long as
1050  // the timer interval (if it is not replaced again by this function),
1051  // before replacing it with the message about remaining disk capacity.
1052  RestartTimer();
1053 }
1054 
1055 void ProjectManager::SetStatusText( const TranslatableString &text, int number )
1056 {
1057  auto &project = mProject;
1058  auto pWindow = ProjectWindow::Find( &project );
1059  if ( !pWindow )
1060  return;
1061  auto &window = *pWindow;
1062  window.GetStatusBar()->SetStatusText(text.Translation(), number);
1063 }
1064 
1066 {
1067  if (iMinutes < 1)
1068  // Less than a minute...
1069  return XO("Less than 1 minute");
1070 
1071  // Calculate
1072  int iHours = iMinutes / 60;
1073  int iMins = iMinutes % 60;
1074 
1075  auto sHours = XP( "%d hour", "%d hours", 0 )( iHours );
1076 
1077  auto sMins = XP( "%d minute", "%d minutes", 0 )( iMins );
1078 
1079  /* i18n-hint: A time in hours and minutes. Only translate the "and". */
1080  return XO("%s and %s.").Format( sHours, sMins );
1081 }
1082 
1083 // This routine will give an estimate of how many
1084 // minutes of recording time we have available.
1085 // The calculations made are based on the user's current
1086 // preferences.
1088  auto &project = mProject;
1089 
1090  // Obtain the current settings
1091  auto oCaptureFormat = QualitySettings::SampleFormatChoice();
1092  if (lCaptureChannels == 0)
1093  lCaptureChannels = AudioIORecordChannels.Read();
1094 
1095  // Find out how much free space we have on disk
1096  wxLongLong lFreeSpace = ProjectFileIO::Get( project ).GetFreeDiskSpace();
1097  if (lFreeSpace < 0) {
1098  return 0;
1099  }
1100 
1101  // Calculate the remaining time
1102  double dRecTime = 0.0;
1103  double bytesOnDiskPerSample = SAMPLE_SIZE_DISK(oCaptureFormat);
1104  dRecTime = lFreeSpace.GetHi() * 4294967296.0 + lFreeSpace.GetLo();
1105  dRecTime /= bytesOnDiskPerSample;
1106  dRecTime /= lCaptureChannels;
1107  dRecTime /= ProjectRate::Get( project ).GetRate();
1108 
1109  // Convert to minutes before returning
1110  int iRecMins = (int)round(dRecTime / 60.0);
1111  return iRecMins;
1112 }
ImportMIDI.h
AdornedRulerPanel::Destroy
static void Destroy(AudacityProject &project)
Definition: AdornedRulerPanel.cpp:910
SelectionBar::Get
static SelectionBar & Get(AudacityProject &project)
Definition: SelectionBar.cpp:138
WaveTrack.h
InitProjectWindow
void InitProjectWindow(ProjectWindow &window)
Definition: ProjectManager.cpp:360
ProjectManager::ProjectChooser::operator()
AudacityProject & operator()(bool openingProjectFile)
May create a fresh project.
Definition: ProjectManager.cpp:930
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:241
field
#define field(n, t)
Definition: ImportAUP.cpp:167
anonymous_namespace{TrackSelectHandle.cpp}::Message
TranslatableString Message(unsigned trackCount)
Definition: TrackSelectHandle.cpp:38
AllProjects::begin
const_iterator begin() const
Definition: Project.cpp:24
ProjectSelectionManager.h
ProjectStatus.h
ToolManager.h
wxFileNameWrapper.h
ProjectFileIO.h
ProjectAudioManager::Get
static ProjectAudioManager & Get(AudacityProject &project)
Definition: ProjectAudioManager.cpp:55
ProjectManager::SetStatusText
void SetStatusText(const TranslatableString &text, int number)
Definition: ProjectManager.cpp:1055
ProjectManager::mTimer
std::unique_ptr< wxTimer > mTimer
Definition: ProjectManager.h:128
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
ProjectManager::SafeToOpenProjectInto
static bool SafeToOpenProjectInto(AudacityProject &proj)
False when it is unsafe to overwrite proj with contents of an .aup3 file.
Definition: ProjectManager.cpp:892
SelectionBar.h
ProjectWindow::FixScrollbars
void FixScrollbars()
Definition: ProjectWindow.cpp:1009
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
SpectralSelectionBar.h
EVT_COMMAND
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:92
ProjectWindow::GetTopPanel
wxPanel * GetTopPanel()
Definition: ProjectWindow.h:56
SAMPLE_SIZE_DISK
#define SAMPLE_SIZE_DISK(SampleFormat)
Return the size on disk of one uncompressed sample (bytes)
Definition: SampleFormat.h:59
Project.h
Import.h
ProjectRate::Get
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:42
ModuleManager.h
ProjectStatusEvent
Definition: ProjectStatus.h:32
ProjectWindow::GetMainPanel
wxPanel * GetMainPanel()
Definition: ProjectWindow.h:55
Clipboard.h
ProjectFileManager::OpenFile
static AudacityProject * OpenFile(const ProjectChooserFn &chooser, const FilePath &fileName, bool addtohistory=true)
Definition: ProjectFileManager.cpp:869
TrackPanel.h
ToolManager::Get
static ToolManager & Get(AudacityProject &project)
Definition: ToolManager.cpp:356
ProjectManager::ProjectChooser
Callable object that supplies the chooser argument of ProjectFileManager::OpenFile.
Definition: ProjectManager.h:63
ToolManager::CreateWindows
void CreateWindows()
Definition: ToolManager.cpp:437
TrackPanel::Get
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:227
XO
#define XO(s)
Definition: Internat.h:31
GetActiveProject
AUDACITY_DLL_API std::weak_ptr< AudacityProject > GetActiveProject()
Definition: ActiveProject.cpp:24
ProjectFileIO::Get
static ProjectFileIO & Get(AudacityProject &project)
Definition: ProjectFileIO.cpp:266
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:44
WaveTrackFactory::Destroy
static void Destroy(AudacityProject &project)
Definition: WaveTrack.cpp:2907
ProjectSettings.h
ProjectWindow::Get
static ProjectWindow & Get(AudacityProject &project)
Definition: ProjectWindow.cpp:535
ProjectManager::OpenProject
static AudacityProject * OpenProject(AudacityProject *pGivenProject, const FilePath &fileNameArg, bool addtohistory, bool reuseNonemptyProject)
Open a file into an AudacityProject, returning the project, or nullptr for failure.
Definition: ProjectManager.cpp:949
ProjectAudioManager.h
ProjectAudioIO::Get
static ProjectAudioIO & Get(AudacityProject &project)
Definition: ProjectAudioIO.cpp:22
AllProjects::Remove
value_type Remove(AudacityProject &project)
Definition: Project.cpp:44
ProjectManager::OnCloseWindow
void OnCloseWindow(wxCloseEvent &event)
Definition: ProjectManager.cpp:618
anonymous_namespace{TimeTrackVRulerControls.cpp}::ruler
Ruler & ruler()
Definition: TimeTrackVRulerControls.cpp:34
ProjectManager::ResetProjectToEmpty
void ResetProjectToEmpty()
Definition: ProjectManager.cpp:972
ProjectManager::SaveWindowSize
static void SaveWindowSize()
Definition: ProjectManager.cpp:110
ClientData::Site::RegisteredFactory
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
ProjectManager::OnTimer
void OnTimer(wxTimerEvent &event)
Definition: ProjectManager.cpp:1000
ProjectManager::ProjectChooser::mpGivenProject
AudacityProject * mpGivenProject
Definition: ProjectManager.h:84
ThemeBase::Bitmap
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1209
Setting::Read
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:128
AllProjects::empty
bool empty() const
Definition: Project.h:46
ProjectManager::ProjectChooser::mpUsedProject
AudacityProject * mpUsedProject
Definition: ProjectManager.h:85
ProjectWindowBase::GetProject
AudacityProject & GetProject()
Definition: ProjectWindowBase.h:29
SpectralSelectionBar::SetListener
void SetListener(SpectralSelectionBarListener *l)
AllProjects::size
size_t size() const
Definition: Project.cpp:19
wxDEFINE_EVENT
wxDEFINE_EVENT(EVT_OPEN_AUDIO_FILE, wxCommandEvent)
TitleRestorer
Definition: ProjectFileIO.h:317
FileNames::IsMidi
FILES_API bool IsMidi(const FilePath &fName)
AdornedRulerPanel::Get
static AdornedRulerPanel & Get(AudacityProject &project)
Definition: AdornedRulerPanel.cpp:899
ModuleManager::Dispatch
int Dispatch(ModuleDispatchTypes type)
Definition: ModuleManager.cpp:381
ProjectManager::Get
static ProjectManager & Get(AudacityProject &project)
Definition: ProjectManager.cpp:70
TrackUtilities.h
ProjectManager::~ProjectManager
~ProjectManager() override
mainStatusBarField
@ mainStatusBarField
Definition: ProjectStatus.h:26
FilePath
wxString FilePath
Definition: Project.h:20
MixerToolBar::Get
static MixerToolBar & Get(AudacityProject &project)
Definition: MixerToolBar.cpp:71
ProjectWindow::HandleResize
void HandleResize()
Definition: ProjectWindow.cpp:1206
ProjectManager::ProjectManager
ProjectManager(AudacityProject &project)
Definition: ProjectManager.cpp:80
ProjectFileManager::Get
static ProjectFileManager & Get(AudacityProject &project)
Definition: ProjectFileManager.cpp:66
BasicUI::Get
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:26
ProjectManager::GetHoursMinsString
TranslatableString GetHoursMinsString(int iMinutes)
Definition: ProjectManager.cpp:1065
ProjectSelectionManager::Get
static ProjectSelectionManager & Get(AudacityProject &project)
Definition: ProjectSelectionManager.cpp:36
SpectralSelectionBar::Get
static SpectralSelectionBar & Get(AudacityProject &project)
ProjectManager::OnReconnectionFailure
void OnReconnectionFailure(wxCommandEvent &event)
Definition: ProjectManager.cpp:603
ProjectWindow
A top-level window associated with a project, and handling scrollbars and zooming.
Definition: ProjectWindow.h:32
ToolManager::RegenerateTooltips
void RegenerateTooltips()
Definition: ToolManager.cpp:688
ToolManager::GetTopDock
ToolDock * GetTopDock()
Definition: ToolManager.cpp:1037
ModuleManager::Get
static ModuleManager & Get()
Definition: ModuleManager.cpp:395
wxDECLARE_EXPORTED_EVENT
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_OPEN_AUDIO_FILE, wxCommandEvent)
ProjectManager::ProjectChooser::Commit
void Commit()
Commit the creation of any fresh project or changes to the existing project.
Definition: ProjectManager.cpp:944
AllProjects::Add
void Add(const value_type &pProject)
This invalidates iterators.
Definition: Project.cpp:58
name
const TranslatableString name
Definition: Distortion.cpp:98
ProjectManager::New
static AudacityProject * New()
Definition: ProjectManager.cpp:529
ProjectManager::sbWindowRectAlreadySaved
static bool sbWindowRectAlreadySaved
Definition: ProjectManager.h:132
MenuCreator::CreateMenusAndCommands
void CreateMenusAndCommands(AudacityProject &project)
Definition: Menus.cpp:382
format
int format
Definition: ExportPCM.cpp:56
ProjectManager::mProject
AudacityProject & mProject
Definition: ProjectManager.h:126
Importer::SetLastOpenType
static void SetLastOpenType(const FileNames::FileType &type)
Definition: Import.cpp:224
ProjectWindow::GetMainPage
wxWindow * GetMainPage()
Definition: ProjectWindow.h:54
UndoManager.h
ProjectFileManager.h
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
WaveTrackFactory::Reset
static WaveTrackFactory & Reset(AudacityProject &project)
Definition: WaveTrack.cpp:2900
ProjectRate::GetRate
double GetRate() const
Definition: ProjectRate.cpp:68
TimeToolBar::Get
static TimeToolBar & Get(AudacityProject &project)
Definition: TimeToolBar.cpp:64
ToolManager::LayoutToolBars
void LayoutToolBars()
Definition: ToolManager.cpp:1131
UndoManager::ClearStates
void ClearStates()
Definition: UndoManager.cpp:253
ProjectAudioManager::Stop
void Stop(bool stopStream=true)
Definition: ProjectAudioManager.cpp:495
TitleRestorer::sProjNumber
wxString sProjNumber
Definition: ProjectFileIO.h:321
MixerToolBar.h
GetDefaultWindowRect
void GetDefaultWindowRect(wxRect *defRect)
Definition: ProjectWindow.cpp:92
ProjectManager.h
TrackUtilities::DoRemoveTracks
void DoRemoveTracks(AudacityProject &project)
Definition: TrackUtilities.cpp:22
Menus.h
TimeToolBar.h
theTheme
THEME_API Theme theTheme
Definition: Theme.cpp:79
ProjectWindows.h
accessors for certain important windows associated with each project
ProjectManager
Object associated with a project for high-level management of the project's lifetime,...
Definition: ProjectManager.h:34
ToolManager::Destroy
void Destroy()
Definition: ToolManager.cpp:487
ProjectWindow::UpdateStatusWidths
void UpdateStatusWidths()
Definition: ProjectWindow.cpp:1231
Clipboard::Get
static Clipboard & Get()
Definition: Clipboard.cpp:29
SelectionBar::SetListener
void SetListener(SelectionBarListener *l)
Definition: SelectionBar.cpp:383
ProjectFileManager::IsAlreadyOpen
static bool IsAlreadyOpen(const FilePath &projPathName)
Definition: ProjectFileManager.cpp:847
WindowAccessible.h
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
QualitySettings.h
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
FileHistory.h
ProjectManager::GetEstimatedRecordingMinsLeftOnDisk
int GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels=0)
Definition: ProjectManager.cpp:1087
XP
#define XP(sing, plur, n)
Definition: Internat.h:96
sbClosingAll
static bool sbClosingAll
Definition: ProjectManager.cpp:611
ProjectFileIO::GetFreeDiskSpace
wxLongLong GetFreeDiskSpace() const
Definition: ProjectFileIO.cpp:2226
ProjectHistory::RollbackState
void RollbackState()
Definition: ProjectHistory.cpp:117
UndoManager::Get
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:57
AudioIO.h
ProjectStatus::Get
static ProjectStatus & Get(AudacityProject &project)
Definition: ProjectStatus.cpp:35
QualitySettings::SampleFormatChoice
PROJECT_RATE_API sampleFormat SampleFormatChoice()
Definition: QualitySettings.cpp:38
ProjectWindow::GetNormalizedWindowState
wxRect GetNormalizedWindowState() const
Definition: ProjectWindow.h:93
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
FileNames.h
SetActiveProject
void SetActiveProject(AudacityProject *project)
Definition: ActiveProject.cpp:29
TimeToolBar::SetListener
void SetListener(TimeToolBarListener *l)
Definition: TimeToolBar.cpp:178
AudacityMessageBox.h
GetProjectFrame
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
Definition: ProjectWindows.cpp:72
ProjectWindow::Find
static ProjectWindow * Find(AudacityProject *pProject)
Definition: ProjectWindow.cpp:545
AdornedRulerPanel.h
MenuManager::Get
static MenuManager & Get(AudacityProject &project)
Definition: Menus.cpp:70
AllProjects
Definition: Project.h:35
AudacityProjectTimerID
const int AudacityProjectTimerID
Definition: ProjectManager.cpp:62
ProjectHistory.h
ProjectRate.h
an object holding per-project preferred sample rate
ActiveProject.h
Handle changing of active project and keep global project pointer.
ProjectManager::ProjectChooser::~ProjectChooser
~ProjectChooser()
Destroy any fresh project, or rollback the existing project, unless committed.
Definition: ProjectManager.cpp:915
ProjectManager::OpenFiles
static void OpenFiles(AudacityProject *proj)
Definition: ProjectManager.cpp:866
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1189
GetNextWindowPlacement
void GetNextWindowPlacement(wxRect *nextRect, bool *pMaximized, bool *pIconized)
Definition: ProjectWindow.cpp:139
ProjectFileManager::Import
bool Import(const FilePath &fileName, bool addToHistory=true)
Definition: ProjectFileManager.cpp:1207
ProjectStatusEvent::mField
StatusBarField mField
Definition: ProjectStatus.h:36
FileNames::CompareNoCase
FILES_API int CompareNoCase(const wxString &first, const wxString &second)
SelectUtilities::DoSelectAll
void DoSelectAll(AudacityProject &project)
Definition: SelectUtilities.cpp:139
ProjectInitialized
@ ProjectInitialized
Definition: ModuleConstants.h:32
ProjectWindow.h
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
AudioIO::Get
static AudioIO * Get()
Definition: AudioIO.cpp:141
safenew
#define safenew
Definition: MemoryX.h:10
ProjectManager::OnStatusChange
void OnStatusChange(ProjectStatusEvent &)
Definition: ProjectManager.cpp:1028
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
ProjectManager::OnOpenAudioFile
void OnOpenAudioFile(wxCommandEvent &event)
Definition: ProjectManager.cpp:851
sProjectManagerKey
static AudacityProject::AttachedObjects::RegisteredFactory sProjectManagerKey
Definition: ProjectManager.cpp:64
SelectUtilities.h
END_EVENT_TABLE
END_EVENT_TABLE()
ProjectManager::sbSkipPromptingForSave
static bool sbSkipPromptingForSave
Definition: ProjectManager.h:133
ProjectAudioIO.h
ArrayOf< char >
TrackPanel::Destroy
static void Destroy(AudacityProject &project)
Definition: TrackPanel.cpp:237
ProjectWindow::GetVerticalScrollBar
wxScrollBar & GetVerticalScrollBar()
Definition: ProjectWindow.h:109
ProjectManager::RestartTimer
void RestartTimer()
Definition: ProjectManager.cpp:992
ProjectClosing
@ ProjectClosing
Definition: ModuleConstants.h:33
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
ProjectManager::SetClosingAll
static void SetClosingAll(bool closing)
Definition: ProjectManager.cpp:613
AudioIORecordChannels
IntSetting AudioIORecordChannels
Definition: AudioIOBase.cpp:943
ProjectFileManager::ShowOpenDialog
static wxArrayString ShowOpenDialog(FileNames::Operation op, const FileNames::FileType &extraType={})
Show an open dialogue for opening audio files, and possibly other sorts of files.
Definition: ProjectFileManager.cpp:805
ProjectWindow::GetHorizontalScrollBar
wxScrollBar & GetHorizontalScrollBar()
Definition: ProjectWindow.h:110
TitleRestorer::sProjName
wxString sProjName
Definition: ProjectFileIO.h:322
DoImportMIDI
bool DoImportMIDI(AudacityProject &project, const FilePath &fileName)
Definition: ImportMIDI.cpp:37