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:
parent
2fbfd3e0a5
commit
cbf1bb558e
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)...);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
206
src/WaveClip.cpp
206
src/WaveClip.cpp
|
@ -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 ®ion = 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 ®ion = 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;
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 © 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
|
||||
|
|
|
@ -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({});
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue