AUP3: Removes OD code related to project file handling

This removes all of the OnDemand code embedded throughout
    the main codebase. Individual files related specifically
    to OD have been left in place, but removed from the build.
This commit is contained in:
Leland Lucius 2020-06-21 18:21:43 -05:00
parent 2fbfd3e0a5
commit cbf1bb558e
46 changed files with 58 additions and 1183 deletions

View File

@ -105,7 +105,6 @@ It handles initialization and termination by subclassing wxApp.
#include "SplashDialog.h"
#include "FFT.h"
#include "BlockFile.h"
#include "ondemand/ODManager.h"
#include "widgets/AudacityMessageBox.h"
#include "prefs/DirectoriesPrefs.h"
#include "prefs/GUIPrefs.h"
@ -428,9 +427,6 @@ static void QuitAudacity(bool bForce)
#endif
CloseScreenshotTools();
//release ODManager Threads
ODManager::Quit();
//print out profile if we have one by deleting it
//temporarily commented out till it is added to all projects
//DELETE Profiler::Instance();

View File

@ -16,8 +16,6 @@
#include "wxFileNameWrapper.h" // member variable
#include "ondemand/ODTaskThread.h"
#include <functional>
class XMLWriter;
@ -100,16 +98,15 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
/// of any lock when it goes out of scope. Call mLocker.reset() to unlock it sooner.
struct GetFileNameResult {
const wxFileName &name;
ODLocker mLocker;
GetFileNameResult(const wxFileName &name_, ODLocker &&locker = ODLocker{})
: name{ name_ }, mLocker{ std::move(locker) } {}
GetFileNameResult(const wxFileName &name_)
: name{ name_ } {}
GetFileNameResult(const GetFileNameResult&) PROHIBITED;
GetFileNameResult &operator= (const GetFileNameResult&) PROHIBITED;
GetFileNameResult(GetFileNameResult &&that)
: name{ that.name }, mLocker{ std::move(that.mLocker) } {}
: name{ that.name } {}
};
virtual GetFileNameResult GetFileName() const;
virtual void SetFileName(wxFileNameWrapper &&name);
@ -145,15 +142,6 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
/// Returns TRUE if this block references another disk file
virtual bool IsAlias() const { return false; }
/// Returns TRUE if this block's complete summary has been computed and is ready (for OD)
virtual bool IsSummaryAvailable() const {return true;}
/// Returns TRUE if this block's complete data is ready to be accessed by Read()
virtual bool IsDataAvailable() const {return true;}
/// Returns TRUE if the summary has not yet been written, but is actively being computed and written to disk
virtual bool IsSummaryBeingComputed(){return false;}
/// Create a NEW BlockFile identical to this, using the given filename
virtual BlockFilePtr Copy(wxFileNameWrapper &&newFileName) = 0;

View File

@ -335,12 +335,6 @@ list( APPEND SOURCES
blockfile/LegacyAliasBlockFile.h
blockfile/LegacyBlockFile.cpp
blockfile/LegacyBlockFile.h
blockfile/NotYetAvailableException.cpp
blockfile/NotYetAvailableException.h
# blockfile/ODDecodeBlockFile.cpp
# blockfile/ODDecodeBlockFile.h
# blockfile/ODPCMAliasBlockFile.cpp
# blockfile/ODPCMAliasBlockFile.h
blockfile/PCMAliasBlockFile.cpp
blockfile/PCMAliasBlockFile.h
blockfile/SilentBlockFile.cpp
@ -696,24 +690,6 @@ list( APPEND SOURCES
menus/ViewMenus.cpp
menus/WindowMenus.cpp
# On demand loading
# ondemand/ODComputeSummaryTask.cpp
# ondemand/ODComputeSummaryTask.h
# ondemand/ODDecodeFFmpegTask.cpp
# ondemand/ODDecodeFFmpegTask.h
# ondemand/ODDecodeFlacTask.cpp
# ondemand/ODDecodeFlacTask.h
# ondemand/ODDecodeTask.cpp
# ondemand/ODDecodeTask.h
# ondemand/ODManager.cpp
# ondemand/ODManager.h
# ondemand/ODTask.cpp
# ondemand/ODTask.h
# ondemand/ODTaskThread.cpp
# ondemand/ODTaskThread.h
# ondemand/ODWaveTrackTaskQueue.cpp
# ondemand/ODWaveTrackTaskQueue.h
# Preferences
prefs/BatchPrefs.cpp

View File

@ -610,17 +610,10 @@ bool ShowDependencyDialogIfNeeded(AudacityProject *project,
if (!isSaving)
{
auto msg =
#ifdef EXPERIMENTAL_OD_DATA
XO("Your project is currently self-contained; it does not depend on any external audio files. \
\n\nIf you change the project to a state that has external dependencies on imported \
files, it will no longer be self-contained. If you then Save without copying those files in, \
you may lose data.");
#else
XO("Your project is self-contained; it does not depend on any external audio files. \
\n\nSome older Audacity projects may not be self-contained, and care \n\
is needed to keep their external dependencies in the right place.\n\
New projects will be self-contained and are less risky.");
#endif
AudacityMessageBox(
msg,
XO("Dependency Check"),
@ -632,22 +625,8 @@ New projects will be self-contained and are less risky.");
if (isSaving)
{
#ifdef EXPERIMENTAL_OD_DATA
wxString action =
FileFormatsSaveWithDependenciesSetting.Read();
if (action == wxT("copy"))
{
// User always wants to remove dependencies
RemoveDependencies(project, aliasedFiles);
return true;
}
if (action == wxT("never"))
// User never wants to remove dependencies
return true;
#else
RemoveDependencies(project, aliasedFiles);
return true;
#endif
}
DependencyDialog dlog(pWindow, -1, project, aliasedFiles, isSaving);

View File

@ -791,10 +791,6 @@ void DirManager::ProjectSetter::Impl::Commit()
".DS_Store", // Other project files should already have been removed.
XO("Cleaning up cache directories"),
kCleanTopDirToo);
//This destroys the empty dirs of the OD block files, which are yet to come.
//Dont know if this will make the project dirty, but I doubt it. (mchinen)
// count += RecursivelyEnumerate(cleanupLoc2, dirlist, wxEmptyString, false, true);
}
}
@ -1214,7 +1210,6 @@ BlockFilePtr DirManager::NewBlockFile( const BlockFileFactory &factory )
mBlockFileHash[fileName] = newBlockFile;
auto &aliasName = newBlockFile->GetExternalFileName();
if ( aliasName.IsOk() )
//OD TODO: check to see if we need to remove this when done decoding.
//I don't immediately see a place where aliased files remove when a file is closed.
aliasList.push_back( aliasName.GetFullPath() );
return newBlockFile;
@ -1279,19 +1274,11 @@ BlockFilePtr DirManager::CopyBlockFile(const BlockFilePtr &b)
// as the existing file
newFile.SetExt(fn.GetExt());
//some block files such as ODPCMAliasBlockFIle don't always have
//a summary file, so we should check before we copy.
if(b->IsSummaryAvailable())
{
if( !FileNames::DoCopyFile(fn.GetFullPath(),
newFile.GetFullPath()) )
// Disk space exhaustion, maybe
throw FileException{
FileException::Cause::Write, newFile };
}
// Done with fn
result.mLocker.reset();
if( !FileNames::DoCopyFile(fn.GetFullPath(),
newFile.GetFullPath()) )
// Disk space exhaustion, maybe
throw FileException{
FileException::Cause::Write, newFile };
b2 = b->Copy(std::move(newFile));
@ -1414,51 +1401,15 @@ std::pair<bool, FilePath> DirManager::LinkOrCopyToNewProjectDirectory(
newPath = newFileName.GetFullPath();
if (newFileName != oldFileNameRef) {
//check to see that summary exists before we copy.
bool summaryExisted = f->IsSummaryAvailable();
auto oldPath = oldFileNameRef.GetFullPath();
if (summaryExisted) {
bool success = false;
if (link)
success = FileNames::HardLinkFile( oldPath, newPath );
if (!success)
link = false,
success = FileNames::DoCopyFile( oldPath, newPath );
if (!success)
return { false, {} };
}
if (!summaryExisted && (f->IsSummaryAvailable() || f->IsSummaryBeingComputed())) {
// PRL: These steps apply only in case of "on-demand" files that have
// not completed their asynchronous loading yet -- a very unusual
// circumstance.
// We will need to remember the old file name, so copy it
wxFileName oldFileName{ oldFileNameRef };
// Now we can free any lock (and should, if as the comment below says, we need
// the other threads to progress)
result.mLocker.reset();
f->SetFileName(std::move(newFileName));
//there is a small chance that the summary has begun to be computed on a different thread with the
//original filename. we need to catch this case by waiting for it to finish and then copy.
//block to make sure OD files don't get written while we are changing file names.
//(It is important that OD files set this lock while computing their summary files.)
while(f->IsSummaryBeingComputed() && !f->IsSummaryAvailable())
::wxMilliSleep(50);
//check to make sure the oldfile exists.
//if it doesn't, we can assume it was written to the NEW name, which is fine.
if (oldFileName.FileExists())
{
bool ok = FileNames::DoCopyFile(oldPath, newPath);
if (!ok)
return { false, {} };
}
}
bool success = false;
if (link)
success = FileNames::HardLinkFile( oldPath, newPath );
if (!success)
link = false,
success = FileNames::DoCopyFile( oldPath, newPath );
if (!success)
return { false, {} };
}
return { true, newPath };
@ -1522,16 +1473,12 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
bool needToRename = false;
wxBusyCursor busy;
BlockHash::iterator iter = mBlockFileHash.begin();
std::vector< BlockFile::ReadLock > readLocks;
while (iter != mBlockFileHash.end())
{
BlockFilePtr b = iter->second.lock();
if (b) {
if (fName.IsOk() && b->GetExternalFileName() == fName) {
needToRename = true;
//ODBlocks access the aliased file on another thread, so we need to pause them before this continues.
readLocks.push_back( b->LockForRead() );
}
}
++iter;
@ -1552,7 +1499,6 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
fullPath,
renamedFullPath);
// Destruction of readLocks puts things back where they were
return false;
}
else
@ -1633,7 +1579,7 @@ void DirManager::FindMissingAUFs(
const wxString &key = iter->first;
BlockFilePtr b = iter->second.lock();
if (b) {
if (b->IsAlias() && b->IsSummaryAvailable())
if (b->IsAlias())
{
/* don't look in hash; that might find files the user moved
that the Blockfile abstraction can't find itself */

View File

@ -123,15 +123,6 @@
// Allow keyboard seeking before initial playback position
//#define EXPERIMENTAL_SEEK_BEHIND_CURSOR
// Michael Chinen, 08.Oct 2009
// Use on-demand importing for FLAC. Has issues with opening projects that
// have not been fully imported in builds without FLAC support, so disabled for
// 2.0 release
//#define EXPERIMENTAL_OD_FLAC
// similarly for FFmpeg:
// Won't build on Fedora 17 or Windows VC++, per http://bugzilla.audacityteam.org/show_bug.cgi?id=539.
//#define EXPERIMENTAL_OD_FFMPEG 1
// Paul Licameli (PRL) 5 Oct 2014
#define EXPERIMENTAL_SPECTRAL_EDITING
@ -253,11 +244,6 @@
// PRL 31 July 2018
#define EXPERIMENTAL_DRAGGABLE_PLAY_HEAD
// JKC 29 July 2019
// OD_DATA made experimental. It is on the way out because
// it is dangerous and has too many bugs. See bug 536 for example.
//#do not define EXPERIMENTAL_OD_DATA
// Jonatã Bolzan Loss 31 Dec 2019
#define EXPERIMENTAL_TIMER_TOOLBAR

View File

@ -394,7 +394,7 @@ int ufile_close(AVIOContext *pb);
struct streamContext;
// common utility functions
// utility calls that are shared with ImportFFmpeg and ODDecodeFFmpegTask
// utility calls that are shared with ImportFFmpeg
streamContext *import_ffmpeg_read_next_frame(AVFormatContext* formatContext,
streamContext** streams,
unsigned int numStreams);

View File

@ -320,8 +320,6 @@ static OSType sf_header_mactype(int format)
#endif // __WXMAC__
ODLock libSndFileMutex;
int SFFileCloser::operator() (SNDFILE *sf) const
{
auto err = SFCall<int>(sf_close, sf);

View File

@ -103,13 +103,9 @@ extern FileExtensions sf_get_all_extensions();
wxString sf_normalize_name(const char *name);
// This function wrapper uses a mutex to serialize calls to the SndFile library.
#include "ondemand/ODTaskThread.h"
extern ODLock libSndFileMutex;
template<typename R, typename F, typename... Args>
inline R SFCall(F fun, Args&&... args)
{
ODLocker locker{ &libSndFileMutex };
return fun(std::forward<Args>(args)...);
}

View File

@ -738,3 +738,11 @@ char *FileNames::VerifyFilename(const wxString &s, bool input)
return (char *) (const char *) mFilename;
}
#endif
//using this with wxStringArray::Sort will give you a list that
//is alphabetical, without depending on case. If you use the
//default sort, you will get strings with 'R' before 'a', because it is in caps.
int FileNames::CompareNoCase(const wxString& first, const wxString& second)
{
return first.CmpNoCase(second);
}

View File

@ -179,6 +179,9 @@ namespace FileNames
#if defined(__WXMSW__)
char *VerifyFilename(const wxString &s, bool input = true);
#endif
// wxString compare function for sorting case, which is needed to load correctly.
int CompareNoCase(const wxString& first, const wxString& second);
};
// Use this macro to wrap all filenames and pathnames that get

View File

@ -28,7 +28,6 @@ but it will probably work fine if you use it on a high level.
#define __AUDACITY_PROFILER__
#include <vector>
#include <time.h>
#include "ondemand/ODTaskThread.h"
#define BEGIN_TASK_PROFILING(TASK_DESCRIPTION) Profiler::Instance()->Begin(__FILE__,__LINE__,TASK_DESCRIPTION)
@ -60,8 +59,6 @@ class Profiler
//List of current Task to do.
std::vector<std::unique_ptr<TaskProfile>> mTasks;
//mutex for above variable
ODLock mTasksMutex;
};

View File

@ -13,7 +13,6 @@
#include "Project.h"
#include "KeyboardCapture.h"
#include "ondemand/ODTaskThread.h"
#include <wx/display.h>
#include <wx/frame.h>
@ -48,7 +47,6 @@ auto AllProjects::rend() const -> const_reverse_iterator
auto AllProjects::Remove( AudacityProject &project ) -> value_type
{
ODLocker locker{ &Mutex() };
auto start = begin(), finish = end(), iter = std::find_if(
start, finish,
[&]( const value_type &ptr ){ return ptr.get() == &project; }
@ -62,7 +60,6 @@ auto AllProjects::Remove( AudacityProject &project ) -> value_type
void AllProjects::Add( const value_type &pProject )
{
ODLocker locker{ &Mutex() };
gAudacityProjects.push_back( pProject );
}
@ -88,12 +85,6 @@ bool AllProjects::Close( bool force )
return true;
}
ODLock &AllProjects::Mutex()
{
static ODLock theMutex;
return theMutex;
};
int AudacityProject::mProjectCounter=0;// global counter.
/* Define Global Variables */

View File

@ -23,7 +23,6 @@ class wxFrame;
class wxWindow;
class AudacityProject;
class ODLock;
AUDACITY_DLL_API AudacityProject *GetActiveProject();
@ -65,10 +64,6 @@ public:
// This invalidates iterators
void Add( const value_type &pProject );
/// In case you must iterate in a non-main thread, use this to prevent
/// changes in the set of open projects
static ODLock &Mutex();
// Return true if all projects do close (always so if force == true)
// But if return is false, that means the user cancelled close of at least
// one un-saved project.

View File

@ -21,7 +21,6 @@
#include "Internat.h"
#include "MemoryX.h"
#include "MissingAliasFileDialog.h"
#include "ondemand/ODManager.h"
#include "widgets/MultiDialog.h"
#include "widgets/ProgressDialog.h"
@ -142,8 +141,8 @@ XO("Project check of \"%s\" folder \
if (action == 2)
{
// silence the blockfiles by yanking the filename
// This is done, eventually, in PCMAliasBlockFile::ReadData()
// and ODPCMAliasBlockFile::ReadData, in the stack of b->Recover().
// This is done, eventually, in PCMAliasBlockFile::ReadData(),
// in the stack of b->Recover().
// There, if the mAliasedFileName is bad, it zeroes the data.
wxFileNameWrapper dummy;
dummy.Clear();
@ -373,7 +372,7 @@ other projects. \
}
}
if ((nResult != FSCKstatus_CLOSE_REQ) && !ODManager::HasLoadedODFlag())
if (nResult != FSCKstatus_CLOSE_REQ)
{
// Remove any empty directories.
ProgressDialog pProgress(

View File

@ -45,15 +45,10 @@ Paul Licameli split from AudacityProject.cpp
#include "WaveClip.h"
#include "WaveTrack.h"
#include "wxFileNameWrapper.h"
#include "blockfile/ODDecodeBlockFile.h"
#include "export/Export.h"
#include "import/Import.h"
#include "import/ImportMIDI.h"
#include "commands/CommandContext.h"
#include "ondemand/ODComputeSummaryTask.h"
#include "ondemand/ODDecodeFlacTask.h"
#include "ondemand/ODManager.h"
#include "ondemand/ODTask.h"
#include "toolbars/SelectionBar.h"
#include "widgets/AudacityMessageBox.h"
#include "widgets/ErrorDialog.h"
@ -170,29 +165,6 @@ auto ProjectFileManager::ReadProjectFile( const FilePath &fileName )
XMLFileReader xmlFile;
#ifdef EXPERIMENTAL_OD_DATA
// 'Lossless copy' projects have dependencies. We need to always copy-in
// these dependencies when converting to a normal project.
auto oldAction = FileFormatsCopyOrEditSetting.Read();
bool oldAsk =
gPrefs->ReadBool(wxT("/Warnings/CopyOrEditUncompressedDataAsk"), true);
if (oldAction != wxT("copy"))
FileFormatsCopyOrEditSetting.Write( wxT("copy") );
if (oldAsk)
gPrefs->Write(wxT("/Warnings/CopyOrEditUncompressedDataAsk"), (long) false);
gPrefs->Flush();
auto cleanup = finally( [&] {
// and restore old settings if necessary.
if (oldAction != wxT("copy"))
FileFormatsCopyOrEditSetting.Write( oldAction );
if (oldAsk)
gPrefs->Write(wxT("/Warnings/CopyOrEditUncompressedDataAsk"), (long) true);
gPrefs->Flush();
} );
#endif
bool bParseSuccess = xmlFile.Parse(&projectFileIO, fileName);
bool err = false;
@ -228,82 +200,6 @@ auto ProjectFileManager::ReadProjectFile( const FilePath &fileName )
};
}
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
unsigned int ProjectFileManager::GetODFlags( const WaveTrack &track )
{
unsigned int ret = 0;
for ( const auto &clip : track.GetClips() )
{
auto sequence = clip->GetSequence();
const auto &blocks = sequence->GetBlockArray();
for ( const auto &block : blocks ) {
const auto &file = block.f;
if(!file->IsDataAvailable())
ret |= (static_cast< ODDecodeBlockFile * >( &*file ))->GetDecodeType();
else if(!file->IsSummaryAvailable())
ret |= ODTask::eODPCMSummary;
}
}
return ret;
}
void ProjectFileManager::EnqueueODTasks()
{
//check the ODManager to see if we should add the tracks to the ODManager.
//this flag would have been set in the HandleXML calls from above, if there were
//OD***Blocks.
if(ODManager::HasLoadedODFlag())
{
auto &project = mProject;
auto &tracks = TrackList::Get( project );
std::vector<std::unique_ptr<ODTask>> newTasks;
//std::vector<ODDecodeTask*> decodeTasks;
unsigned int createdODTasks=0;
for (auto wt : tracks.Any<WaveTrack>()) {
//check the track for blocks that need decoding.
//There may be more than one type e.g. FLAC/FFMPEG/lame
unsigned int odFlags = GetODFlags( *wt );
//add the track to the already created tasks that correspond to the od flags in the wavetrack.
for(unsigned int i=0;i<newTasks.size();i++) {
if(newTasks[i]->GetODType() & odFlags)
newTasks[i]->AddWaveTrack(wt->SharedPointer< WaveTrack >());
}
//create whatever NEW tasks we need to.
//we want at most one instance of each class for the project
while((odFlags|createdODTasks) != createdODTasks)
{
std::unique_ptr<ODTask> newTask;
#ifdef EXPERIMENTAL_OD_FLAC
if(!(createdODTasks&ODTask::eODFLAC) && (odFlags & ODTask::eODFLAC)) {
newTask = std::make_unique<ODDecodeFlacTask>();
createdODTasks = createdODTasks | ODTask::eODFLAC;
}
else
#endif
if(!(createdODTasks&ODTask::eODPCMSummary) && (odFlags & ODTask::eODPCMSummary)) {
newTask = std::make_unique<ODComputeSummaryTask>();
createdODTasks = createdODTasks | ODTask::eODPCMSummary;
}
else {
wxPrintf("unrecognized OD Flag in block file.\n");
//TODO:ODTODO: display to user. This can happen when we build audacity on a system that doesnt have libFLAC
break;
}
if(newTask)
{
newTask->AddWaveTrack(wt->SharedPointer< WaveTrack >());
newTasks.push_back(std::move(newTask));
}
}
}
for(unsigned int i=0;i<newTasks.size();i++)
ODManager::Instance()->AddNewTask(std::move(newTasks[i]));
}
}
bool ProjectFileManager::Save()
{
// Prompt for file name?
@ -594,11 +490,6 @@ bool ProjectFileManager::DoSave (const bool fromSaveAs,
auto &tracks = TrackList::Get( proj );
for ( auto t : tracks.Any() ) {
mLastSavedTracks->Add(t->Duplicate());
//only after the xml has been saved we can mark it saved.
//thus is because the OD blockfiles change on background thread while this is going on.
// if(const auto wt = track_cast<WaveTrack*>(dupT))
// wt->MarkSaved();
}
UndoManager::Get( proj ).StateSaved();
@ -1392,14 +1283,10 @@ void ProjectFileManager::OpenFile(const FilePath &fileNameArg, bool addtohistory
// might throw.
bool closed = false;
auto cleanup = finally( [&] {
//release the flag.
ODManager::UnmarkLoadedODFlag();
if (! closed ) {
if ( bParseSuccess ) {
// This is a no-fail:
dirManager.FillBlockfilesCache();
EnqueueODTasks();
}
// For an unknown reason, OSX requires that the project window be

View File

@ -53,9 +53,6 @@ public:
};
ReadProjectResults ReadProjectFile( const FilePath &fileName );
static unsigned int GetODFlags( const WaveTrack &track );
void EnqueueODTasks();
// To be called when closing a project that has been saved, so that
// block files are not erased
void CloseLock();

View File

@ -17,8 +17,6 @@ Paul Licameli split from ProjectManager.cpp
#include "UndoManager.h"
#include "ViewInfo.h"
#include "WaveTrack.h"
#include "ondemand/ODComputeSummaryTask.h"
#include "ondemand/ODManager.h"
static AudacityProject::AttachedObjects::RegisteredFactory sProjectHistoryKey {
[]( AudacityProject &project ) {
@ -142,41 +140,12 @@ void ProjectHistory::PopState(const UndoState &state)
TrackList *const tracks = state.tracks.get();
dstTracks.Clear();
bool odUsed = false;
std::unique_ptr<ODComputeSummaryTask> computeTask;
for (auto t : tracks->Any())
{
auto copyTrack = dstTracks.Add(t->Duplicate());
//add the track to OD if the manager exists. later we might do a more rigorous check...
copyTrack->TypeSwitch( [&](WaveTrack *wt) {
//if the ODManager hasn't been initialized, there's no chance this track has OD blocks since this
//is a "Redo" operation.
//TODO: update this to look like the update loop in OpenFile that handles general purpose ODTasks.
//BUT, it is too slow to go thru every blockfile and check the odtype, so maybe put a flag in wavetrack
//that gets unset on OD Completion, (and we could also update the drawing there too.) The hard part is that
//we would need to watch every possible way a OD Blockfile could get inserted into a wavetrack and change the
//flag there.
if(ODManager::IsInstanceCreated())
{
if(!odUsed)
{
computeTask = std::make_unique<ODComputeSummaryTask>();
odUsed=true;
}
// PRL: Is it correct to add all tracks to one task, even if they
// are not partnered channels? Rather than
// make one task for each?
computeTask->AddWaveTrack(wt->SharedPointer< WaveTrack >());
}
});
dstTracks.Add(t->Duplicate());
}
//add the task.
if(odUsed)
ODManager::Instance()->AddNewTask(std::move(computeTask));
projectFileIO.AutoSave();
}

View File

@ -40,7 +40,6 @@ Paul Licameli split from AudacityProject.cpp
#include "wxFileNameWrapper.h"
#include "import/Import.h"
#include "import/ImportMIDI.h"
#include "ondemand/ODManager.h"
#include "prefs/QualityPrefs.h"
#include "toolbars/MixerToolBar.h"
#include "toolbars/SelectionBar.h"
@ -324,11 +323,8 @@ public:
// Experiment shows that this function can be reached while there is no
// catch block above in wxWidgets. So stop all exceptions here.
return GuardedCall< bool > ( [&] {
//sort by OD non OD. load Non OD first so user can start editing asap.
wxArrayString sortednames(filenames);
sortednames.Sort(CompareNoCaseFileName);
ODManager::Pauser pauser;
sortednames.Sort(FileNames::CompareNoCase);
auto cleanup = finally( [&] {
ProjectWindow::Get( *mProject ).HandleResize(); // Adjust scrollers for NEW track sizes.
@ -843,11 +839,8 @@ void ProjectManager::OpenFiles(AudacityProject *proj)
return;
}
//sort selected files by OD status.
//For the open menu we load OD first so user can edit asap.
//first sort selectedFiles.
selectedFiles.Sort(CompareNoCaseFileName);
ODManager::Pauser pauser;
selectedFiles.Sort(FileNames::CompareNoCase);
auto cleanup = finally( [] {
Importer::SetLastOpenType({});
@ -962,36 +955,6 @@ void ProjectManager::OnTimer(wxTimerEvent& WXUNUSED(event))
SetStatusText(sMessage, mainStatusBarField);
}
}
else if(ODManager::IsInstanceCreated())
{
//if we have some tasks running, we should say something about it.
int numTasks = ODManager::Instance()->GetTotalNumTasks();
if(numTasks)
{
TranslatableString msg;
float ratioComplete= ODManager::Instance()->GetOverallPercentComplete();
if(ratioComplete>=1.0f)
{
//if we are 100 percent complete and there is still a task in the queue, we should wake the ODManager
//so it can clear it.
//signal the od task queue loop to wake up so it can remove the tasks from the queue and the queue if it is empty.
ODManager::Instance()->SignalTaskQueueLoop();
msg = XO("On-demand import and waveform calculation complete.");
}
else if(numTasks>1)
msg = XO(
"Import(s) complete. Running %d on-demand waveform calculations. Overall %2.0f%% complete.")
.Format( numTasks, ratioComplete * 100.0 );
else
msg = XO(
"Import complete. Running an on-demand waveform calculation. %2.0f%% complete.")
.Format( ratioComplete * 100.0 );
SetStatusText(msg, mainStatusBarField);
}
}
// As also with the TrackPanel timer: wxTimer may be unreliable without
// some restarts

View File

@ -1414,25 +1414,15 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
break;
case 256:
// Read triples
//check to see if summary data has been computed
if (seqBlock.f->IsSummaryAvailable())
// Ignore the return value.
// This function fills with zeroes if read fails
seqBlock.f->Read256(temp.get(), startPosition, num);
else
//otherwise, mark the display as not yet computed
blockStatus = -1 - b;
// Ignore the return value.
// This function fills with zeroes if read fails
seqBlock.f->Read256(temp.get(), startPosition, num);
break;
case 65536:
// Read triples
//check to see if summary data has been computed
if (seqBlock.f->IsSummaryAvailable())
// Ignore the return value.
// This function fills with zeroes if read fails
seqBlock.f->Read64K(temp.get(), startPosition, num);
else
//otherwise, mark the display as not yet computed
blockStatus = -1 - b;
// Ignore the return value.
// This function fills with zeroes if read fails
seqBlock.f->Read64K(temp.get(), startPosition, num);
break;
}
@ -1653,11 +1643,6 @@ void Sequence::Delete(sampleCount start, sampleCount len)
if (len < 0 || start < 0 || start + len > mNumSamples)
THROW_INCONSISTENCY_EXCEPTION;
//TODO: add a ref-deref mechanism to SeqBlock/BlockArray so we don't have to make this a critical section.
//On-demand threads iterate over the mBlocks and the GUI thread deletes them, so for now put a mutex here over
//both functions,
DeleteUpdateMutexLocker locker(*this);
const unsigned int numBlocks = mBlock.size();
const unsigned int b0 = FindBlock(start);

View File

@ -15,7 +15,6 @@
#include "SampleFormat.h"
#include "xml/XMLTagHandler.h"
#include "ondemand/ODTaskThread.h"
#include "audacity/Types.h"
@ -189,25 +188,6 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
BlockArray &GetBlockArray() { return mBlock; }
const BlockArray &GetBlockArray() const { return mBlock; }
///
void LockDeleteUpdateMutex(){mDeleteUpdateMutex.Lock();}
void UnlockDeleteUpdateMutex(){mDeleteUpdateMutex.Unlock();}
// RAII idiom wrapping the functions above
struct DeleteUpdateMutexLocker {
DeleteUpdateMutexLocker(Sequence &sequence)
: mSequence(sequence)
{
mSequence.LockDeleteUpdateMutex();
}
~DeleteUpdateMutexLocker()
{
mSequence.UnlockDeleteUpdateMutex();
}
private:
Sequence &mSequence;
};
private:
//
@ -233,9 +213,6 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
bool mErrorOpening{ false };
///To block the Delete() method against the ODCalcSummaryTask::Update() method
ODLock mDeleteUpdateMutex;
//
// Private methods
//

View File

@ -78,9 +78,6 @@ is time to refresh some aspect of the screen.
#include "TrackPanelResizerCell.h"
#include "WaveTrack.h"
#include "ondemand/ODManager.h"
#include "ondemand/ODTask.h"
#include "tracks/ui/TrackControls.h"
#include "tracks/ui/TrackView.h"
#include "tracks/ui/TrackVRulerControls.h"
@ -308,8 +305,6 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
this);
auto theProject = GetProject();
wxTheApp->Bind(EVT_ODTASK_UPDATE, &TrackPanel::OnODTask, this);
theProject->Bind(EVT_ODTASK_COMPLETE, &TrackPanel::OnODTask, this);
theProject->Bind(
EVT_PROJECT_SETTINGS_CHANGE, &TrackPanel::OnProjectSettingsChange, this);
theProject->Bind(
@ -462,14 +457,6 @@ void TrackPanel::OnTimer(wxTimerEvent& )
mTimeCount = 0;
}
///Handles the redrawing necessary for tasks as they partially update in the
///background, or finish.
void TrackPanel::OnODTask(wxCommandEvent & WXUNUSED(event))
{
//todo: add track data to the event - check to see if the project contains it before redrawing.
Refresh(false);
}
void TrackPanel::OnProjectSettingsChange( wxCommandEvent &event )
{
event.Skip();

View File

@ -101,7 +101,6 @@ class AUDACITY_DLL_API TrackPanel final
void OnSize( wxSizeEvent & );
void OnIdle(wxIdleEvent & event);
void OnTimer(wxTimerEvent& event);
void OnODTask(wxCommandEvent &event);
void OnProjectSettingsChange(wxCommandEvent &event);
void OnTrackFocusChange( wxCommandEvent &event );

View File

@ -85,7 +85,6 @@ UndoManager::UndoManager( AudacityProject &project )
{
current = -1;
saved = -1;
ResetODChangesFlag();
}
UndoManager::~UndoManager()
@ -392,13 +391,12 @@ void UndoManager::Redo(const Consumer &consumer)
bool UndoManager::UnsavedChanges() const
{
return (saved != current) || HasODChangesFlag();
return (saved != current);
}
void UndoManager::StateSaved()
{
saved = current;
ResetODChangesFlag();
}
// currently unused
@ -412,26 +410,3 @@ void UndoManager::StateSaved()
// }
//}
///to mark as unsaved changes without changing the state/tracks.
void UndoManager::SetODChangesFlag()
{
mODChangesMutex.Lock();
mODChanges=true;
mODChangesMutex.Unlock();
}
bool UndoManager::HasODChangesFlag() const
{
bool ret;
mODChangesMutex.Lock();
ret=mODChanges;
mODChangesMutex.Unlock();
return ret;
}
void UndoManager::ResetODChangesFlag()
{
mODChangesMutex.Lock();
mODChanges=false;
mODChangesMutex.Unlock();
}

View File

@ -51,7 +51,6 @@
#include <vector>
#include <wx/event.h> // to declare custom event types
#include "ondemand/ODTaskThread.h"
#include "ClientData.h"
#include "SelectedRegion.h"
@ -168,11 +167,6 @@ class AUDACITY_DLL_API UndoManager final
// void Debug(); // currently unused
///to mark as unsaved changes without changing the state/tracks.
void SetODChangesFlag();
bool HasODChangesFlag() const;
void ResetODChangesFlag();
private:
AudacityProject &mProject;
@ -185,10 +179,6 @@ class AUDACITY_DLL_API UndoManager final
SpaceArray space;
unsigned long long mClipboardSpaceUsage {};
bool mODChanges;
mutable ODLock mODChangesMutex;//mODChanges is accessed from many threads.
};
#endif

View File

@ -57,7 +57,6 @@ public:
, max(0)
, rms(0)
, bl(0)
, numODPixels(0)
{
}
@ -72,16 +71,11 @@ public:
, max(len)
, rms(len)
, bl(len)
, numODPixels(0)
{
//find the number of OD pixels - the only way to do this is by recounting since we've lost some old cache.
numODPixels = CountODPixels(0, len);
}
~WaveCache()
{
ClearInvalidRegions();
}
int dirty;
@ -94,174 +88,6 @@ public:
std::vector<float> max;
std::vector<float> rms;
std::vector<int> bl;
int numODPixels;
class InvalidRegion
{
public:
InvalidRegion(size_t s, size_t e)
: start(s), end(e)
{}
//start and end pixel count. (not samples)
size_t start;
size_t end;
};
//Thread safe call to add a NEW region to invalidate. If it overlaps with other regions, it unions the them.
void AddInvalidRegion(sampleCount sampleStart, sampleCount sampleEnd)
{
//use pps to figure out where we are. (pixels per second)
if(pps ==0)
return;
double samplesPerPixel = rate/pps;
//rate is SR, start is first time of the waveform (in second) on cache
long invalStart = (sampleStart.as_double() - start*rate) / samplesPerPixel ;
long invalEnd = (sampleEnd.as_double() - start*rate)/samplesPerPixel +1; //we should cover the end..
//if they are both off the cache boundary in the same direction, the cache is missed,
//so we are safe, and don't need to track this one.
if((invalStart<0 && invalEnd <0) || (invalStart>=(long)len && invalEnd >= (long)len))
return;
//in all other cases, we need to clip the boundries so they make sense with the cache.
//for some reason, the cache is set up to access up to array[len], not array[len-1]
if(invalStart <0)
invalStart =0;
else if(invalStart > (long)len)
invalStart = len;
if(invalEnd <0)
invalEnd =0;
else if(invalEnd > (long)len)
invalEnd = len;
ODLocker locker(&mRegionsMutex);
//look thru the region array for a place to insert. We could make this more spiffy than a linear search
//but right now it is not needed since there will usually only be one region (which grows) for OD loading.
bool added=false;
if(mRegions.size())
{
for(size_t i=0;i<mRegions.size();i++)
{
//if the regions intersect OR are pixel adjacent
InvalidRegion &region = mRegions[i];
if((long)region.start <= (invalEnd+1)
&& ((long)region.end + 1) >= invalStart)
{
//take the union region
if((long)region.start > invalStart)
region.start = invalStart;
if((long)region.end < invalEnd)
region.end = invalEnd;
added=true;
break;
}
//this bit doesn't make sense because it assumes we add in order - now we go backwards after the initial OD finishes
// //this array is sorted by start/end points and has no overlaps. If we've passed all possible intersections, insert. The array will remain sorted.
// if(region.end < invalStart)
// {
// mRegions.insert(
// mRegions.begin() + i,
// InvalidRegion{ invalStart, invalEnd }
// );
// break;
// }
}
}
if(!added)
{
InvalidRegion newRegion(invalStart, invalEnd);
mRegions.insert(mRegions.begin(), newRegion);
}
//now we must go and patch up all the regions that overlap. Overlapping regions will be adjacent.
for(size_t i=1;i<mRegions.size();i++)
{
//if the regions intersect OR are pixel adjacent
InvalidRegion &region = mRegions[i];
InvalidRegion &prevRegion = mRegions[i - 1];
if(region.start <= prevRegion.end+1
&& region.end + 1 >= prevRegion.start)
{
//take the union region
if(region.start > prevRegion.start)
region.start = prevRegion.start;
if(region.end < prevRegion.end)
region.end = prevRegion.end;
mRegions.erase(mRegions.begin()+i-1);
//musn't forget to reset cursor
i--;
}
//if we are past the end of the region we added, we are past the area of regions that might be oversecting.
if(invalEnd < 0 || (long)region.start > invalEnd)
{
break;
}
}
}
//lock before calling these in a section. unlock after finished.
int GetNumInvalidRegions() const {return mRegions.size();}
size_t GetInvalidRegionStart(int i) const {return mRegions[i].start;}
size_t GetInvalidRegionEnd(int i) const {return mRegions[i].end;}
void ClearInvalidRegions()
{
mRegions.clear();
}
void LoadInvalidRegion(int ii, Sequence *sequence, bool updateODCount)
{
const auto invStart = GetInvalidRegionStart(ii);
const auto invEnd = GetInvalidRegionEnd(ii);
//before check number of ODPixels
int regionODPixels = 0;
if (updateODCount)
regionODPixels = CountODPixels(invStart, invEnd);
sequence->GetWaveDisplay(&min[invStart],
&max[invStart],
&rms[invStart],
&bl[invStart],
invEnd - invStart,
&where[invStart]);
//after check number of ODPixels
if (updateODCount)
{
const int regionODPixelsAfter = CountODPixels(invStart, invEnd);
numODPixels -= (regionODPixels - regionODPixelsAfter);
}
}
void LoadInvalidRegions(Sequence *sequence, bool updateODCount)
{
//invalid regions are kept in a sorted array.
for (int i = 0; i < GetNumInvalidRegions(); i++)
LoadInvalidRegion(i, sequence, updateODCount);
}
int CountODPixels(size_t startIn, size_t endIn)
{
using namespace std;
const int *begin = &bl[0];
return count_if(begin + startIn, begin + endIn, bind2nd(less<int>(), 0));
}
protected:
std::vector<InvalidRegion> mRegions;
ODLock mRegionsMutex;
};
static void ComputeSpectrumUsingRealFFTf
@ -487,18 +313,9 @@ bool WaveClip::IsClipStartAfterClip(double t) const
///Delete the wave cache - force redraw. Thread-safe
void WaveClip::ClearWaveCache()
{
ODLocker locker(&mWaveCacheMutex);
mWaveCache = std::make_unique<WaveCache>();
}
///Adds an invalid region to the wavecache so it redraws that portion only.
void WaveClip::AddInvalidRegion(sampleCount startSample, sampleCount endSample)
{
ODLocker locker(&mWaveCacheMutex);
if(mWaveCache!=NULL)
mWaveCache->AddInvalidRegion(startSample,endSample);
}
namespace {
inline
@ -564,7 +381,7 @@ fillWhere(std::vector<sampleCount> &where, size_t len, double bias, double corre
//
bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
double pixelsPerSecond, bool &isLoadingOD) const
double pixelsPerSecond) const
{
const bool allocated = (display.where != 0);
@ -588,9 +405,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
pWhere = &display.ownWhere;
}
else {
// Lock the list of invalid regions
ODLocker locker(&mWaveCacheMutex);
const double tstep = 1.0 / pixelsPerSecond;
const double samplesPerPixel = mRate * tstep;
@ -609,8 +423,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
if (match &&
mWaveCache->start == t0 &&
mWaveCache->len >= numPixels) {
mWaveCache->LoadInvalidRegions(mSequence.get(), true);
mWaveCache->ClearInvalidRegions();
// Satisfy the request completely from the cache
display.min = &mWaveCache->min[0];
@ -618,7 +430,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
display.rms = &mWaveCache->rms[0];
display.bl = &mWaveCache->bl[0];
display.where = &mWaveCache->where[0];
isLoadingOD = mWaveCache->numODPixels > 0;
return true;
}
@ -662,12 +473,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
if (oldCache) {
//TODO: only load inval regions if
//necessary. (usually is the case, so no rush.)
//also, we should be updating the NEW cache, but here we are patching the old one up.
oldCache->LoadInvalidRegions(mSequence.get(), false);
oldCache->ClearInvalidRegions();
// Copy what we can from the old cache.
const int length = copyEnd - copyBegin;
const size_t sizeFloats = length * sizeof(float);
@ -763,13 +568,11 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
p1-p0,
&where[p0]))
{
isLoadingOD=false;
return false;
}
}
}
//find the number of OD pixels - the only way to do this is by recounting
if (!allocated) {
// Now report the results
display.min = min;
@ -777,13 +580,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
display.rms = rms;
display.bl = bl;
display.where = &(*pWhere)[0];
isLoadingOD = mWaveCache->numODPixels > 0;
}
else {
using namespace std;
isLoadingOD =
count_if(display.ownBl.begin(), display.ownBl.end(),
bind2nd(less<int>(), 0)) > 0;
}
return true;

View File

@ -15,7 +15,6 @@
#include "Audacity.h"
#include "SampleFormat.h"
#include "ondemand/ODTaskThread.h"
#include "xml/XMLTagHandler.h"
#include "RealFFTf.h"
@ -258,7 +257,7 @@ public:
/** Getting high-level data for screen display and clipping
* calculations and Contrast */
bool GetWaveDisplay(WaveDisplay &display,
double t0, double pixelsPerSecond, bool &isLoadingOD) const;
double t0, double pixelsPerSecond) const;
bool GetSpectrogram(WaveTrackCache &cache,
const float *& spectrogram,
const sampleCount *& where,
@ -343,9 +342,6 @@ public:
///Delete the wave cache - force redraw. Thread-safe
void ClearWaveCache();
///Adds an invalid region to the wavecache so it redraws that portion only.
void AddInvalidRegion(sampleCount startSample, sampleCount endSample);
//
// XMLTagHandler callback methods for loading and saving
//
@ -378,7 +374,6 @@ protected:
std::unique_ptr<Envelope> mEnvelope;
mutable std::unique_ptr<WaveCache> mWaveCache;
mutable ODLock mWaveCacheMutex {};
mutable std::unique_ptr<SpecCache> mSpecCache;
SampleBuffer mAppendBuffer {};
size_t mAppendBufferLen { 0 };

View File

@ -2481,13 +2481,6 @@ void WaveTrack::ClearWaveCaches()
clip->ClearWaveCache();
}
///Adds an invalid region to the wavecache so it redraws that portion only.
void WaveTrack::AddInvalidRegion(sampleCount startSample, sampleCount endSample)
{
for (const auto &clip : mClips)
clip->AddInvalidRegion(startSample, endSample);
}
int WaveTrack::GetAutoSaveIdent() const
{
return mAutoSaveIdent;

View File

@ -230,9 +230,6 @@ private:
///Invalidates all clips' wavecaches. Careful, This may not be threadsafe.
void ClearWaveCaches();
///Adds an invalid region to the wavecache so it redraws that portion only.
void AddInvalidRegion(sampleCount startSample, sampleCount endSample);
///
/// MM: Now that each wave track can contain multiple clips, we don't
/// have a continuous space of samples anymore, but we simulate it,

View File

@ -211,7 +211,6 @@ bool SimpleBlockFile::WriteSimpleBlockFile(
ArrayOf<char> cleanup;
if (!summaryData)
summaryData = /*BlockFile::*/CalcSummary(sampleData, sampleLen, format, cleanup);
//mchinen:allowing virtual override of calc summary for ODDecodeBlockFile.
// PRL: cleanup fixes a possible memory leak!
size_t nBytesToWrite = sizeof(header);

View File

@ -38,7 +38,6 @@
#include "../WaveTrack.h"
#include "../wxFileNameWrapper.h"
#include "../widgets/ProgressDialog.h"
#include "../ondemand/ODManager.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
#include "../widgets/NumericTextCtrl.h"
@ -2250,13 +2249,6 @@ void Effect::ReplaceProcessedTracks(const bool bGoodResult)
{
// Replace mTracks entry with the NEW track
mTracks->Replace(t, o);
// If the track is a wave track,
// Swap the wavecache track the ondemand task uses, since now the NEW
// one will be kept in the project
if (ODManager::IsInstanceCreated()) {
ODManager::Instance()->ReplaceWaveTrack( t, o );
}
}
}

View File

@ -441,17 +441,6 @@ void EffectLoudness::FreeBuffers()
bool EffectLoudness::GetTrackRMS(WaveTrack* track, float& rms)
{
// Since we need complete summary data, we need to block until the OD tasks are done for this track
// This is needed for track->GetMinMax
// TODO: should we restrict the flags to just the relevant block files (for selections)
while (ProjectFileManager::GetODFlags(*track)) {
// update the gui
if (ProgressResult::Cancelled == mProgress->Update(
0, XO("Waiting for waveform to finish computing...")) )
return false;
wxMilliSleep(100);
}
// set mRMS. No progress bar here as it's fast.
float _rms = track->GetRMS(mCurT0, mCurT1); // may throw
rms = _rms;

View File

@ -371,17 +371,6 @@ bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const TranslatableSt
if(mGain)
{
// Since we need complete summary data, we need to block until the OD tasks are done for this track
// This is needed for track->GetMinMax
// TODO: should we restrict the flags to just the relevant block files (for selections)
while (ProjectFileManager::GetODFlags( *track )) {
// update the gui
if (ProgressResult::Cancelled == mProgress->Update(
0, XO("Waiting for waveform to finish computing...")) )
return false;
wxMilliSleep(100);
}
// set mMin, mMax. No progress bar here as it's fast.
auto pair = track->GetMinMax(mCurT0, mCurT1); // may throw
min = pair.first, max = pair.second;

View File

@ -29,8 +29,6 @@ Licensed under the GNU General Public License v2 or later
#include "../FFmpeg.h" // which brings in avcodec.h, avformat.h
#include "../WaveClip.h"
#include "../blockfile/ODDecodeBlockFile.h"
#include "../ondemand/ODManager.h"
#ifndef WX_PRECOMP
// Include your minimal set of headers here, or wx.h
#include <wx/window.h>
@ -158,11 +156,6 @@ static const auto exts = {
#include "../WaveTrack.h"
#include "ImportPlugin.h"
#ifdef EXPERIMENTAL_OD_FFMPEG
#include "../ondemand/ODDecodeFFmpegTask.h"
#endif
class FFmpegImportFileHandle;
/// A representative of FFmpeg loader in
@ -276,10 +269,6 @@ private:
//!< First dimension - streams,
//!< second - channels of a stream.
//!< Length is mNumStreams
#ifdef EXPERIMENTAL_OD_FFMPEG
bool mUsingOD;
#endif
};
@ -561,75 +550,6 @@ ProgressResult FFmpegImportFileHandle::Import(TrackFactory *trackFactory,
// The result of Import() to be returned. It will be something other than zero if user canceled or some error appears.
auto res = ProgressResult::Success;
#ifdef EXPERIMENTAL_OD_FFMPEG
mUsingOD = false;
gPrefs->Read(wxT("/Library/FFmpegOnDemand"), &mUsingOD);
//at this point we know the file is good and that we have to load the number of channels in mScs[s]->m_stream->codec->channels;
//so for OD loading we create the tracks and releasee the modal lock after starting the ODTask.
if (mUsingOD) {
std::vector<std::unique_ptr<ODDecodeFFmpegTask>> tasks;
//append blockfiles to each stream and add an individual ODDecodeTask for each one.
s = -1;
for (const auto &stream : mChannels) {
++s;
auto odTask =
std::make_unique<ODDecodeFFmpegTask>(mScs, ODDecodeFFmpegTask::FromList(mChannels), mContext, s);
odTask->CreateFileDecoder(mFilename);
//each stream has different duration. We need to know it if seeking is to be allowed.
sampleCount sampleDuration = 0;
auto sc = scs[s].get();
if (sc->m_stream->duration > 0)
sampleDuration = ((sampleCount)sc->m_stream->duration * sc->m_stream->time_base.num) * sc->m_stream->codec->sample_rate / sc->m_stream->time_base.den;
else
sampleDuration = ((sampleCount)mFormatContext->duration *sc->m_stream->codec->sample_rate) / AV_TIME_BASE;
// wxPrintf(" OD duration samples %qi, sr %d, secs %d\n",sampleDuration, (int)sc->m_stream->codec->sample_rate, (int)sampleDuration/sc->m_stream->codec->sample_rate);
//for each wavetrack within the stream add coded blockfiles
for (int c = 0; c < sc->m_stream->codec->channels; c++) {
auto t = stream[c];
odTask->AddWaveTrack(t);
auto maxBlockSize = t->GetMaxBlockSize();
//use the maximum blockfile size to divide the sections (about 11secs per blockfile at 44.1khz)
for (decltype(sampleDuration) i = 0; i < sampleDuration; i += maxBlockSize) {
const auto blockLen =
limitSampleBufferSize( maxBlockSize, sampleDuration - i );
t->RightmostOrNewClip()->AppendBlockFile(
[&]( wxFileNameWrapper filePath, size_t len ) {
return make_blockfile<ODDecodeBlockFile>(
std::move(filePath), wxFileNameWrapper{ mFilename },
i, len, c, ODTask::eODFFMPEG);
},
blockLen
);
// This only works well for single streams since we assume
// each stream is of the same duration and channels
res = mProgress->Update(
(i+sampleDuration * c +
sampleDuration*sc->m_stream->codec->channels * s
).as_long_long(),
(sampleDuration *
sc->m_stream->codec->channels * mNumStreams
).as_long_long()
);
if (res != ProgressResult::Success)
break;
}
}
tasks.push_back(std::move(odTask));
}
//Now we add the tasks and let them run, or DELETE them if the user cancelled
if (res == ProgressResult::Success)
for (int i = 0; i < (int)tasks.size(); i++)
ODManager::Instance()->AddNewTask(std::move(tasks[i]));
} else {
#endif
// Read next frame.
for (streamContext *sc; (sc = ReadNextFrame()) != NULL && (res == ProgressResult::Success);)
{
@ -667,9 +587,6 @@ ProgressResult FFmpegImportFileHandle::Import(TrackFactory *trackFactory,
}
}
}
#ifdef EXPERIMENTAL_OD_FFMPEG
} // else -- !mUsingOD == true
#endif //EXPERIMENTAL_OD_FFMPEG
// Something bad happened - destroy everything!
if (res == ProgressResult::Cancelled || res == ProgressResult::Failed)

View File

@ -43,7 +43,6 @@
#include "../Tags.h"
#include "../WaveClip.h"
#include "../blockfile/ODDecodeBlockFile.h"
#include "../prefs/QualityPrefs.h"
#include "../widgets/ProgressDialog.h"
@ -76,8 +75,6 @@ static Importer::RegisteredUnusableImportPlugin registered{
#include "../Prefs.h"
#include "../WaveTrack.h"
#include "ImportPlugin.h"
#include "../ondemand/ODDecodeFlacTask.h"
#include "../ondemand/ODManager.h"
#ifdef USE_LIBID3TAG
extern "C" {
@ -178,7 +175,6 @@ private:
bool mStreamInfoDone;
ProgressResult mUpdateResult;
NewChannelGroup mChannels;
std::unique_ptr<ODDecodeFlacTask> mDecoderTask;
};
@ -349,28 +345,6 @@ FLACImportFileHandle::FLACImportFileHandle(const FilePath & name)
bool FLACImportFileHandle::Init()
{
#ifdef EXPERIMENTAL_OD_FLAC
mDecoderTask = std::make_unique<ODDecodeFlacTask>();
ODFlacDecoder* odDecoder = (ODFlacDecoder*)mDecoderTask->CreateFileDecoder(mFilename);
if(!odDecoder || !odDecoder->ReadHeader())
{
return false;
}
//copy the meta data over to the class
mSampleRate=odDecoder->mSampleRate;
mNumChannels=odDecoder->mNumChannels;
mBitsPerSample=odDecoder->mBitsPerSample;
mNumSamples=odDecoder->mNumSamples;
mBitsPerSample=odDecoder->mBitsPerSample;
mFormat=odDecoder->mFormat;
mStreamInfoDone=true;
return true;
#endif
#ifdef LEGACY_FLAC
bool success = mFile->set_filename(OSINPUT(mFilename));
if (!success) {
@ -452,70 +426,15 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
*iter = trackFactory->NewWaveTrack(mFormat, mSampleRate);
}
//Start OD
bool useOD = false;
#ifdef EXPERIMENTAL_OD_FLAC
useOD=true;
#endif
// TODO: Vigilant Sentry: Variable res unused after assignment (error code DA1)
// Should check the result.
#ifdef LEGACY_FLAC
bool res = (mFile->process_until_end_of_file() != 0);
#else
bool res = true;
if(!useOD)
res = (mFile->process_until_end_of_stream() != 0);
bool res = (mFile->process_until_end_of_stream() != 0);
#endif
wxUnusedVar(res);
//add the task to the ODManager
if(useOD)
{
auto fileTotalFrames =
(sampleCount)mNumSamples; // convert from FLAC__uint64
auto maxBlockSize = mChannels.begin()->get()->GetMaxBlockSize();
for (decltype(fileTotalFrames) i = 0; i < fileTotalFrames; i += maxBlockSize) {
const auto blockLen =
limitSampleBufferSize( maxBlockSize, fileTotalFrames - i );
auto iter = mChannels.begin();
for (size_t c = 0; c < mNumChannels; ++c, ++iter)
iter->get()->RightmostOrNewClip()->AppendBlockFile(
[&]( wxFileNameWrapper filePath, size_t len ) {
return make_blockfile<ODDecodeBlockFile>(
std::move(filePath), wxFileNameWrapper{ mFilename },
i, len, c, ODTask::eODFLAC);
},
blockLen
);
mUpdateResult = mProgress->Update(
i.as_long_long(),
fileTotalFrames.as_long_long()
);
if (mUpdateResult != ProgressResult::Success)
break;
}
bool moreThanStereo = mNumChannels>2;
for (const auto &channel : mChannels)
{
mDecoderTask->AddWaveTrack(channel);
if(moreThanStereo)
{
//if we have 3 more channels, they get imported on separate tracks, so we add individual tasks for each.
ODManager::Instance()->AddNewTask(std::move(mDecoderTask));
mDecoderTask = std::make_unique<ODDecodeFlacTask>(); //TODO: see if we need to use clone to keep the metadata.
}
}
//if we have mono or a linked track (stereo), we add ONE task for the one linked wave track
if(!moreThanStereo)
ODManager::Instance()->AddNewTask(std::move(mDecoderTask));
}
//END OD
if (mUpdateResult == ProgressResult::Failed || mUpdateResult == ProgressResult::Cancelled) {
return mUpdateResult;
}
@ -546,11 +465,7 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
FLACImportFileHandle::~FLACImportFileHandle()
{
//don't finish *mFile if we are using OD,
//because it was not initialized in Init().
#ifndef EXPERIMENTAL_OD_FLAC
mFile->finish();
#endif
}
#endif /* USE_LIBFLAC */

View File

@ -39,16 +39,9 @@
#include "../WaveClip.h"
#include "../ShuttleGui.h"
#include "../ondemand/ODManager.h"
#include "../ondemand/ODComputeSummaryTask.h"
#include "../blockfile/ODPCMAliasBlockFile.h"
#include "../prefs/QualityPrefs.h"
#include "../widgets/ProgressDialog.h"
//If OD is enabled, he minimum number of samples a file has to use it.
//Otherwise, we use the older PCMAliasBlockFile method since it should be fast enough.
#define kMinimumODFileSampleSize 44100*30
#ifndef SNDFILE_1
#error Requires libsndfile 1.0 or higher
#endif
@ -288,115 +281,6 @@ auto PCMImportFileHandle::GetFileUncompressedBytes() -> ByteCount
return mInfo.frames * mInfo.channels * SAMPLE_SIZE(mFormat);
}
#ifdef EXPERIMENTAL_OD_DATA
// returns "copy" or "edit" (aliased) as the user selects.
// if the cancel button is hit then "cancel" is returned.
static wxString AskCopyOrEdit()
{
auto oldCopyPref = FileFormatsCopyOrEditSetting.Read();
bool firstTimeAsk = gPrefs->Read(wxT("/Warnings/CopyOrEditUncompressedDataFirstAsk"), true)?true:false;
bool oldAskPref = gPrefs->Read(wxT("/Warnings/CopyOrEditUncompressedDataAsk"), true)?true:false;
// The first time the user is asked we force it to 'copy'.
// This effectively does a one-time change to the preferences.
if (firstTimeAsk) {
if (oldCopyPref != wxT("copy")) {
FileFormatsCopyOrEditSetting.Write( wxT("copy") );
oldCopyPref = wxT("copy");
}
gPrefs->Write(wxT("/Warnings/CopyOrEditUncompressedDataFirstAsk"), (long) false);
gPrefs->Flush();
}
// check the current preferences for whether or not we should ask the user about this.
if (oldAskPref) {
wxString newCopyPref = wxT("copy");
wxDialogWrapper dialog( nullptr, -1, XO("Warning") );
dialog.SetName();
auto clause1 = XO(
"When importing uncompressed audio files you can either copy them into the project,"
" or read them directly from their current location (without copying).\n\n"
);
auto clause2 = (oldCopyPref == wxT("copy"))
? XO("Your current preference is set to copy in.\n\n")
: XO("Your current preference is set to read directly.\n\n")
;
auto clause3 = XO(
"Reading the files directly allows you to play or edit them almost immediately. "
"This is less safe than copying in, because you must retain the files with their "
"original names in their original locations.\n"
"Help > Diagnostics > Check Dependencies will show the original names and locations of any files "
"that you are reading directly.\n\n"
"How do you want to import the current file(s)?"
);
ShuttleGui S{ &dialog, eIsCreating };
S.SetBorder(10);
S
.Position( wxALL | wxEXPAND )
.AddUnits( clause1 + clause2 + clause3, 500);
wxRadioButton *aliasRadio;
wxRadioButton *copyRadio;
wxCheckBox *dontAskNextTimeBox;
S.StartStatic(XO("Choose an import method"));
{
S.SetBorder(0);
copyRadio = S.AddRadioButton(
XXO("Make a &copy of the files before editing (safer)") );
aliasRadio = S.AddRadioButtonToGroup(
XXO("Read the files &directly from the original (faster)") );
dontAskNextTimeBox = S.AddCheckBox(
XXO("Don't &warn again and always use my choice above"),
false);
}
S.EndStatic();
dontAskNextTimeBox->SetName(wxStripMenuCodes(dontAskNextTimeBox->GetLabel()));
wxRadioButton *prefsRadio = oldCopyPref == wxT("copy") ? copyRadio : aliasRadio;
prefsRadio->SetValue(true);
S.SetBorder( 10 );
S.AddStandardButtons( eOkButton | eCancelButton );
dialog.SetSize(dialog.GetBestSize());
dialog.Layout();
dialog.Center();
if (dialog.ShowModal() == wxID_OK) {
if (aliasRadio->GetValue()) {
newCopyPref = wxT("edit");
}
if (dontAskNextTimeBox->IsChecked()) {
gPrefs->Write(wxT("/Warnings/CopyOrEditUncompressedDataAsk"), (long) false);
gPrefs->Flush();
}
} else {
return wxT("cancel");
}
// if the preference changed, save it.
if (newCopyPref != oldCopyPref) {
FileFormatsCopyOrEditSetting.Write( newCopyPref );
gPrefs->Flush();
}
oldCopyPref = newCopyPref;
}
return oldCopyPref;
}
#endif
#ifdef USE_LIBID3TAG
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
@ -414,20 +298,6 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
wxASSERT(mFile.get());
#ifdef EXPERIMENTAL_OD_DATA
// Get the preference / warn the user about aliased files.
wxString copyEdit = AskCopyOrEdit();
if (copyEdit == wxT("cancel"))
return ProgressResult::Cancelled;
// Fall back to "copy" if it doesn't match anything else, since it is safer
bool doEdit = false;
if (copyEdit.IsSameAs(wxT("edit"), false))
doEdit = true;
#endif
CreateProgress();
NewChannelGroup channels(mInfo.channels);
@ -444,82 +314,6 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
auto maxBlockSize = channels.begin()->get()->GetMaxBlockSize();
auto updateResult = ProgressResult::Cancelled;
#ifdef EXPERIMENTAL_OD_DATA
// If the format is not seekable, we must use 'copy' mode,
// because 'edit' mode depends on the ability to seek to an
// arbitrary location in the file.
if (!mInfo.seekable)
doEdit = false;
if (doEdit) {
// If this mode has been selected, we form the tracks as
// aliases to the files we're editing, i.e. ("foo.wav", 12000-18000)
// instead of actually making fresh copies of the samples.
// lets use OD only if the file is longer than 30 seconds. Otherwise, why wake up extra threads.
//todo: make this a user pref.
bool useOD =fileTotalFrames>kMinimumODFileSampleSize;
int updateCounter = 0;
for (decltype(fileTotalFrames) i = 0; i < fileTotalFrames; i += maxBlockSize) {
const auto blockLen =
limitSampleBufferSize( maxBlockSize, fileTotalFrames - i );
auto iter = channels.begin();
for (int c = 0; c < mInfo.channels; ++iter, ++c)
iter->get()->RightmostOrNewClip()->AppendBlockFile(
[&]( wxFileNameWrapper filePath, size_t len ) {
return useOD
? make_blockfile<ODPCMAliasBlockFile>(
std::move(filePath), wxFileNameWrapper{ mFilename },
i, len, c)
: make_blockfile<PCMAliasBlockFile>(
std::move(filePath), wxFileNameWrapper{ mFilename },
i, len, c);
},
blockLen
);
if (++updateCounter == 50) {
updateResult = mProgress->Update(
i.as_long_long(),
fileTotalFrames.as_long_long()
);
updateCounter = 0;
if (updateResult != ProgressResult::Success)
break;
}
}
// One last update for completion
updateResult = mProgress->Update(
fileTotalFrames.as_long_long(),
fileTotalFrames.as_long_long()
);
if(useOD)
{
auto computeTask = std::make_unique<ODComputeSummaryTask>();
bool moreThanStereo = mInfo.channels>2;
for (const auto &channel : channels)
{
computeTask->AddWaveTrack(channel);
if(moreThanStereo)
{
//if we have 3 more channels, they get imported on separate tracks, so we add individual tasks for each.
ODManager::Instance()->AddNewTask(std::move(computeTask));
computeTask = std::make_unique<ODComputeSummaryTask>();
}
}
//if we have a linked track, we add ONE task.
if(!moreThanStereo)
ODManager::Instance()->AddNewTask(std::move(computeTask));
}
}
else
#endif
{
// Otherwise, we're in the "copy" mode, where we read in the actual
// samples from the file and store our own local copy of the

View File

@ -31,8 +31,6 @@
#include "../import/ImportMIDI.h"
#endif // USE_MIDI
#include "../ondemand/ODManager.h"
#include <wx/menu.h>
// private helper classes and functions
@ -388,10 +386,7 @@ void OnImport(const CommandContext &context)
// AudacityProject::Import ?
gPrefs->Write(wxT("/NewImportingSession"), true);
//sort selected files by OD status. Load non OD first so user can edit asap.
//first sort selectedFiles.
selectedFiles.Sort(CompareNoCaseFileName);
ODManager::Pauser pauser;
selectedFiles.Sort(FileNames::CompareNoCase);
auto cleanup = finally( [&] {
Importer::SetLastOpenType({});

View File

@ -118,7 +118,11 @@ void ODComputeSummaryTask::DoSomeInternal()
{
auto waveTrack = mWaveTracks[i].lock();
if(success && waveTrack)
{
#if 0 // LLL: Commented out while removing OD file handling
waveTrack->AddInvalidRegion(blockStartSample,blockEndSample);
#endif
}
}
mWaveTrackMutex.Unlock();
}

View File

@ -104,7 +104,11 @@ void ODDecodeTask::DoSomeInternal()
{
auto waveTrack = mWaveTracks[i].lock();
if(waveTrack)
{
#if 0 // LLL: Commented out while removing OD files handling
waveTrack->AddInvalidRegion(blockStartSample,blockEndSample);
#endif
}
}
mWaveTrackMutex.Unlock();
}

View File

@ -96,18 +96,6 @@ void ImportExportPrefs::PopulateOrExchange(ShuttleGui & S)
S.SetBorder(2);
S.StartScroller();
#ifdef EXPERIMENTAL_OD_DATA
S.StartStatic(XO("When importing audio files"));
{
S.StartRadioButtonGroup(FileFormatsCopyOrEditSetting);
{
S.TieRadioButton();
S.TieRadioButton();
}
S.EndRadioButtonGroup();
}
S.EndStatic();
#endif
S.StartStatic(XO("When exporting tracks to an audio file"));
{
S.StartRadioButtonGroup(ImportExportPrefs::ExportDownMixSetting);

View File

@ -167,14 +167,6 @@ void LibraryPrefs::PopulateOrExchange(ShuttleGui & S)
wxALL | wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
}
S.EndTwoColumn();
#ifdef EXPERIMENTAL_OD_FFMPEG
S
#if !defined(USE_FFMPEG)
.Disable()
#endif
.TieCheckBox(XXO("Allow &background on-demand loading"),
{wxT("/Library/FFmpegOnDemand"), false});
#endif
}
S.EndStatic();
S.EndScroller();

View File

@ -97,18 +97,3 @@ bool ProjectsPrefs::Commit()
return true;
}
#ifdef EXPERIMENTAL_OD_DATA
namespace{
PrefsPanel::Registration sAttachment{ "Projects",
[](wxWindow *parent, wxWindowID winid, AudacityProject *)
{
wxASSERT(parent); // to justify safenew
return safenew ProjectsPrefs(parent, winid);
},
false,
// Register with an explicit ordering hint because this one is
// only conditionally compiled
{ "", { Registry::OrderingHint::After, "ImportExport" } }
};
}
#endif

View File

@ -90,11 +90,6 @@ void WarningsPrefs::PopulateOrExchange(ShuttleGui & S)
S.TieCheckBox(XXO("Missing file &name extension during export"),
{wxT("/Warnings/MissingExtension"),
true});
#ifdef EXPERIMENTAL_OD_DATA
S.TieCheckBox(XXO("&Importing uncompressed audio files"),
{wxT("/Warnings/CopyOrEditUncompressedDataAsk"),
true});
#endif
}
S.EndStatic();
S.EndScroller();

View File

@ -31,7 +31,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../../TrackPanelMouseEvent.h"
#include "../../../../WaveTrack.h"
#include "../../../../effects/RealtimeEffectManager.h"
#include "../../../../ondemand/ODManager.h"
#include "../../../../prefs/PrefsDialog.h"
#include "../../../../prefs/ThemePrefs.h"
#include "../../../../widgets/AudacityMessageBox.h"
@ -824,18 +823,6 @@ void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &)
partnerView.RestorePlacements( view.SavePlacements() );
partnerView.SetMultiView( view.GetMultiView() );
//On Demand - join the queues together.
if (ODManager::IsInstanceCreated())
if (!ODManager::Instance()
->MakeWaveTrackDependent(partner->SharedPointer<WaveTrack>(), pTrack))
{
;
//TODO: in the future, we will have to check the return value of MakeWaveTrackDependent -
//if the tracks cannot merge, it returns false, and in that case we should not allow a merging.
//for example it returns false when there are two different types of ODTasks on each track's queue.
//we will need to display this to the user.
}
ProjectHistory::Get( *project ).PushState(
/* i18n-hint: The string names a track */
XO("Made '%s' a stereo track").Format( pTrack->GetName() ),
@ -862,10 +849,6 @@ void WaveTrackMenuTable::SplitStereo(bool stereo)
if (stereo)
channel->SetPanFromChannelType();
//On Demand - have each channel add its own.
if (ODManager::IsInstanceCreated())
ODManager::Instance()->MakeWaveTrackIndependent(
channel->SharedPointer<WaveTrack>() );
//make sure no channel is smaller than its minimum height
if (view.GetHeight() < view.GetMinimizedHeight())
view.SetHeight(view.GetMinimizedHeight());

View File

@ -325,7 +325,7 @@ void DrawMinMaxRMS(
float zoomMin, float zoomMax,
bool dB, float dBRange,
const float *min, const float *max, const float *rms, const int *bl,
bool /* showProgress */, bool muted)
bool muted)
{
auto &dc = context.dc;
@ -753,7 +753,6 @@ void DrawClipWaveform(TrackPanelDrawingContext &context,
}
WaveDisplay display(hiddenMid.width);
bool isLoadingOD = false;//true if loading on demand block in sequence.
const double pps =
averagePixelsPerSample * rate;
@ -788,8 +787,7 @@ void DrawClipWaveform(TrackPanelDrawingContext &context,
// fisheye moves over the background, there is then less to do when
// redrawing.
if (!clip->GetWaveDisplay(display,
t0, pps, isLoadingOD))
if (!clip->GetWaveDisplay(display,t0, pps))
return;
}
}
@ -840,8 +838,7 @@ void DrawClipWaveform(TrackPanelDrawingContext &context,
// Get a wave display for the fisheye, uncached.
if (rectPortion.width > 0)
if (!clip->GetWaveDisplay(
fisheyeDisplay, t0, -1.0, // ignored
isLoadingOD))
fisheyeDisplay, t0, -1.0)) // ignored
continue; // serious error. just don't draw??
useMin = fisheyeDisplay.min;
useMax = fisheyeDisplay.max;
@ -874,8 +871,7 @@ void DrawClipWaveform(TrackPanelDrawingContext &context,
DrawMinMaxRMS( context, rectPortion, env2,
zoomMin, zoomMax,
dB, dBRange,
useMin, useMax, useRms, useBl,
isLoadingOD, muted );
useMin, useMax, useRms, useBl, muted );
}
else {
bool highlight = false;

View File

@ -35,7 +35,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../ViewInfo.h"
#include "../../WaveClip.h"
#include "../../WaveTrack.h"
#include "../../ondemand/ODManager.h"
#include "../../prefs/SpectrogramSettings.h"
#include "../../../images/Cursors.h"
@ -64,21 +63,6 @@ bool SelectHandle::IsClicked() const
namespace
{
// If we're in OnDemand mode, we may change the tip.
void MaySetOnDemandTip(const Track * t, TranslatableString &tip)
{
wxASSERT(t);
//For OD regions, we need to override and display the percent complete for this task.
//first, make sure it's a wavetrack.
t->TypeSwitch( [&](const WaveTrack *wt) {
//see if the wavetrack exists in the ODManager (if the ODManager exists)
if (!ODManager::IsInstanceCreated())
return;
//ask the wavetrack for the corresponding tip - it may not change tip, but that's fine.
ODManager::Instance()->FillTipForWaveTrack(wt, tip);
});
}
/// Converts a frequency to screen y position.
wxInt64 FrequencyToPosition(const WaveTrack *wt,
double frequency,
@ -785,11 +769,6 @@ UIHandle::Result SelectHandle::Click
StartSelection(pProject);
selectionState.SelectTrack( *pTrack, true, true );
TrackFocus::Get( *pProject ).Set(pTrack);
//On-Demand: check to see if there is an OD thing associated with this track.
pTrack->TypeSwitch( [&](WaveTrack *wt) {
if(ODManager::IsInstanceCreated())
ODManager::Instance()->DemandTrackUpdate(wt,mSelStart);
});
Connect(pProject);
return RefreshAll;
@ -992,8 +971,6 @@ HitTestPreview SelectHandle::Preview
pView.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
}
MaySetOnDemandTip(pTrack.get(), tip);
}
if (tip.empty()) {
tip = XO("Click and drag to select audio");
@ -1239,13 +1216,6 @@ void SelectHandle::AssignSelection
}
viewInfo.selectedRegion.setTimes(sel0, sel1);
//On-Demand: check to see if there is an OD thing associated with this track. If so we want to update the focal point for the task.
if (pTrack && ODManager::IsInstanceCreated())
pTrack->TypeSwitch( [&](WaveTrack *wt) {
ODManager::Instance()->DemandTrackUpdate(wt, sel0);
//sel0 is sometimes less than mSelStart
});
}
void SelectHandle::StartFreqSelection(ViewInfo &viewInfo,