diff --git a/common/components/src/AudioFilePlayer.cpp b/common/components/src/AudioFilePlayer.cpp index 7cb93e3..77e5313 100644 --- a/common/components/src/AudioFilePlayer.cpp +++ b/common/components/src/AudioFilePlayer.cpp @@ -265,9 +265,23 @@ void AudioFilePlayer::valueTreePropertyChanged( triggerAsyncUpdate(); } else if (property == FilePlayback::kPlaybackFile) { attemptCreatePlaybackEngine(); - } else if (property == FileExport::kExportCompleted && - fer_.get().getExportCompleted()) { - attemptCreatePlaybackEngine(); + } else if (property == FileExport::kExportCompleted) { + // When this property is false a new export is starting, so we want to + // destroy the player and wait until export is complete. + // When this property is true we want to attempt to create the playback + // engine again. + if (fer_.get().getExportCompleted()) { + attemptCreatePlaybackEngine(); + } else { + // Destroy the playback engine + playbackEngine_ = nullptr; + // Join any existing creation thread + isBeingDestroyed_ = true; + if (playbackEngineLoaderThread_.joinable()) { + playbackEngineLoaderThread_.join(); + } + isBeingDestroyed_ = false; + } } } @@ -300,6 +314,12 @@ void AudioFilePlayer::attemptCreatePlaybackEngine() { if (kFileToLoad.empty() || kFileToLoad.extension() != ".iamf" || !std::filesystem::exists(kFileToLoad)) { + // If the file doesn't exist or it's a new file, we set the player to a + // stopped state + auto playbackState = fpbr_.get(); + playbackState.setPlayState(FilePlayback::kStop); + fpbr_.update(playbackState); + playbackEngine_ = nullptr; return; } createPlaybackEngine(kFileToLoad); @@ -346,7 +366,8 @@ void AudioFilePlayer::onPlaybackEngineCreated(IAMFPlaybackDevice::Result res) { auto fpb = fpbr_.get(); fpb.setPlayState(FilePlayback::kDisabled); fpbr_.update(fpb); - } else if (res.error == IAMFPlaybackDevice::kEarlyAbortRequested) { + } else if (res.error == IAMFPlaybackDevice::kEarlyAbortRequested || + isBeingDestroyed_) { // Do nothing - destruction was requested } else { playbackEngine_ = std::move(res.device); diff --git a/rendererplugin/src/screens/FileExportScreen.cpp b/rendererplugin/src/screens/FileExportScreen.cpp index c238dc1..77b463b 100644 --- a/rendererplugin/src/screens/FileExportScreen.cpp +++ b/rendererplugin/src/screens/FileExportScreen.cpp @@ -485,7 +485,6 @@ FileExportScreen::FileExportScreen(MainEditor& editor, return; } config.setManualExport(!config.getManualExport()); - repository_->update(config); if (config.getManualExport()) { startTimer_.setEnabled(false); endTimer_.setEnabled(false); @@ -501,7 +500,7 @@ FileExportScreen::FileExportScreen(MainEditor& editor, exportVideoFolder_.setEnabled(false); browseVideoButton_.setEnabled(false); browseVideoSourceButton_.setEnabled(false); - + config.setExportCompleted(false); } else { startTimer_.setEnabled(true); endTimer_.setEnabled(true); @@ -517,15 +516,9 @@ FileExportScreen::FileExportScreen(MainEditor& editor, exportVideoFolder_.setEnabled(true); browseVideoButton_.setEnabled(true); browseVideoSourceButton_.setEnabled(true); - - if (!config.getExportCompleted()) { - // Normally this is handled by the file export processor - // But in manual button cases where the processor is destroyed we need - // to flag it here - config.setExportCompleted(true); - repository_->update(config); - } + config.setExportCompleted(true); } + repository_->update(config); repaint(); }; LOG_ANALYTICS(RendererProcessor::instanceId_, "FileExportScreen initiated.");