1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00
audacity/src/ProjectAudioManager.cpp

203 lines
6.4 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
ProjectAudioManager.cpp
Paul Licameli split from ProjectManager.cpp
**********************************************************************/
#include "ProjectAudioManager.h"
#include <wx/frame.h>
#include <wx/statusbr.h>
#include "AudioIO.h"
#include "AutoRecovery.h"
#include "DirManager.h"
#include "LabelTrack.h"
#include "Menus.h"
#include "Project.h"
#include "ProjectAudioIO.h"
#include "ProjectFileIO.h"
#include "ProjectHistory.h"
#include "ProjectSettings.h"
#include "ProjectWindow.h"
#include "TimeTrack.h"
#include "toolbars/ControlToolBar.h"
#include "widgets/ErrorDialog.h"
#include "widgets/Warning.h"
static AudacityProject::AttachedObjects::RegisteredFactory
sProjectAudioManagerKey {
[]( AudacityProject &project ) {
return std::make_shared< ProjectAudioManager >( project );
}
};
ProjectAudioManager &ProjectAudioManager::Get( AudacityProject &project )
{
return project.AttachedObjects::Get< ProjectAudioManager >(
sProjectAudioManagerKey );
}
const ProjectAudioManager &ProjectAudioManager::Get(
const AudacityProject &project )
{
return Get( const_cast< AudacityProject & >( project ) );
}
ProjectAudioManager::~ProjectAudioManager() = default;
void ProjectAudioManager::OnAudioIORate(int rate)
{
auto &project = mProject;
auto &window = GetProjectFrame( project );
wxString display;
if (rate > 0) {
display = wxString::Format(_("Actual Rate: %d"), rate);
}
else
// clear the status field
;
int x, y;
auto statusBar = window.GetStatusBar();
statusBar->GetTextExtent(display, &x, &y);
int widths[] = {
0,
ControlToolBar::Get( project ).WidthForStatusBar(statusBar),
-1,
x+50
};
statusBar->SetStatusWidths(4, widths);
statusBar->SetStatusText(display, rateStatusBarField);
}
void ProjectAudioManager::OnAudioIOStartRecording()
{
auto &projectFileIO = ProjectFileIO::Get( mProject );
// Before recording is started, auto-save the file. The file will have
// empty tracks at the bottom where the recording will be put into
projectFileIO.AutoSave();
}
// This is called after recording has stopped and all tracks have flushed.
void ProjectAudioManager::OnAudioIOStopRecording()
{
auto &project = mProject;
auto &dirManager = DirManager::Get( project );
auto &projectAudioIO = ProjectAudioIO::Get( project );
auto &projectFileIO = ProjectFileIO::Get( project );
auto &window = ProjectWindow::Get( project );
// Only push state if we were capturing and not monitoring
if (projectAudioIO.GetAudioIOToken() > 0)
{
auto &tracks = TrackList::Get( project );
auto gAudioIO = AudioIO::Get();
auto &intervals = gAudioIO->LostCaptureIntervals();
if (intervals.size()) {
// Make a track with labels for recording errors
auto uTrack = TrackFactory::Get( project ).NewLabelTrack();
auto pTrack = uTrack.get();
tracks.Add( uTrack );
/* i18n-hint: A name given to a track, appearing as its menu button.
The translation should be short or else it will not display well.
At most, about 11 Latin characters.
Dropout is a loss of a short sequence of audio sample data from the
recording */
pTrack->SetName(_("Dropouts"));
long counter = 1;
for (auto &interval : intervals)
pTrack->AddLabel(
SelectedRegion{ interval.first,
interval.first + interval.second },
wxString::Format(wxT("%ld"), counter++),
-2 );
ShowWarningDialog(&window, wxT("DropoutDetected"), _("\
Recorded audio was lost at the labeled locations. Possible causes:\n\
\n\
Other applications are competing with Audacity for processor time\n\
\n\
You are saving directly to a slow external storage device\n\
"
),
false,
_("Turn off dropout detection"));
}
// Add to history
auto &history = ProjectHistory::Get( project );
history.PushState(_("Recorded Audio"), _("Record"));
// Reset timer record
if (IsTimerRecordCancelled())
{
EditActions::DoUndo( project );
ResetTimerRecordCancelled();
}
// Refresh the project window
window.FixScrollbars();
window.RedrawProject();
}
// Write all cached files to disk, if any
dirManager.WriteCacheToDisk();
// Now we auto-save again to get the project to a "normal" state again.
projectFileIO.AutoSave();
}
void ProjectAudioManager::OnAudioIONewBlockFiles(
const AutoSaveFile & blockFileLog)
{
auto &project = mProject;
auto &projectFileIO = ProjectFileIO::Get( project );
// New blockfiles have been created, so add them to the auto-save file
const auto &autoSaveFileName = projectFileIO.GetAutoSaveFileName();
if ( !autoSaveFileName.empty() )
{
wxFFile f{ autoSaveFileName, wxT("ab") };
if (!f.IsOpened())
return; // Keep recording going, there's not much we can do here
blockFileLog.Append(f);
f.Close();
}
}
AudioIOStartStreamOptions
DefaultPlayOptions( AudacityProject &project )
{
auto &projectAudioIO = ProjectAudioIO::Get( project );
AudioIOStartStreamOptions options { &project,
ProjectSettings::Get( project ).GetRate() };
options.captureMeter = projectAudioIO.GetCaptureMeter();
options.playbackMeter = projectAudioIO.GetPlaybackMeter();
auto timeTrack = *TrackList::Get( project ).Any<TimeTrack>().begin();
options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
options.listener = &ProjectAudioManager::Get( project );
return options;
}
AudioIOStartStreamOptions
DefaultSpeedPlayOptions( AudacityProject &project )
{
auto &projectAudioIO = ProjectAudioIO::Get( project );
auto gAudioIO = AudioIO::Get();
auto PlayAtSpeedRate = gAudioIO->GetBestRate(
false, //not capturing
true, //is playing
ProjectSettings::Get( project ).GetRate() //suggested rate
);
AudioIOStartStreamOptions options{ &project, PlayAtSpeedRate };
options.captureMeter = projectAudioIO.GetCaptureMeter();
options.playbackMeter = projectAudioIO.GetPlaybackMeter();
auto timeTrack = *TrackList::Get( project ).Any<TimeTrack>().begin();
options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
options.listener = &ProjectAudioManager::Get( project );
return options;
}