| 379 | } |
| 380 | |
| 381 | void ProjectManager::OnCloseWindow(wxCloseEvent & event) |
| 382 | { |
| 383 | auto &project = mProject; |
| 384 | auto &projectFileIO = ProjectFileIO::Get( project ); |
| 385 | auto &projectFileManager = ProjectFileManager::Get( project ); |
| 386 | const auto &settings = ProjectSettings::Get( project ); |
| 387 | auto &projectAudioIO = ProjectAudioIO::Get( project ); |
| 388 | auto &tracks = TrackList::Get( project ); |
| 389 | auto &viewport = Viewport::Get(project); |
| 390 | auto &window = ProjectWindow::Get( project ); |
| 391 | auto gAudioIO = AudioIO::Get(); |
| 392 | |
| 393 | // We are called for the wxEVT_CLOSE_WINDOW, wxEVT_END_SESSION, and |
| 394 | // wxEVT_QUERY_END_SESSION, so we have to protect against multiple |
| 395 | // entries. This is a hack until the whole application termination |
| 396 | // process can be reviewed and reworked. (See bug #964 for ways |
| 397 | // to exercise the bug that instigated this hack.) |
| 398 | if (window.IsBeingDeleted()) |
| 399 | { |
| 400 | event.Skip(); |
| 401 | return; |
| 402 | } |
| 403 | |
| 404 | if (event.CanVeto() && (::wxIsBusy() || project.mbBusyImporting)) |
| 405 | { |
| 406 | event.Veto(); |
| 407 | return; |
| 408 | } |
| 409 | |
| 410 | // Check to see if we were playing or recording |
| 411 | // audio, and if so, make sure Audio I/O is completely finished. |
| 412 | // The main point of this is to properly push the state |
| 413 | // and flush the tracks once we've completely finished |
| 414 | // recording NEW state. |
| 415 | // This code is derived from similar code in |
| 416 | // AudacityProject::~AudacityProject() and TrackPanel::OnTimer(). |
| 417 | if (projectAudioIO.GetAudioIOToken()>0 && |
| 418 | gAudioIO->IsStreamActive(projectAudioIO.GetAudioIOToken())) { |
| 419 | |
| 420 | // We were playing or recording audio, but we've stopped the stream. |
| 421 | ProjectAudioManager::Get( project ).Stop(); |
| 422 | |
| 423 | projectAudioIO.SetAudioIOToken(0); |
| 424 | viewport.Redraw(); |
| 425 | } |
| 426 | else if (gAudioIO->IsMonitoring()) { |
| 427 | gAudioIO->StopStream(); |
| 428 | } |
| 429 | |
| 430 | // MY: Use routine here so other processes can make same check |
| 431 | bool bHasTracks = !tracks.empty(); |
| 432 | |
| 433 | // We may not bother to prompt the user to save, if the |
| 434 | // project is now empty. |
| 435 | if (!sbSkipPromptingForSave |
| 436 | && event.CanVeto() |
| 437 | && bHasTracks) { |
| 438 | if ( UndoManager::Get( project ).UnsavedChanges() ) { |
nothing calls this directly
no test coverage detected