... This is a more adventurous fix. It avoids changing the schema.
Use non-positive values of SqliteSampleBlock::mBlockID to store lengths of
blocks of silence. Keep SqliteSampleBlock structures in memory (sharing where
possible for recurring block lengths) but do not make corresponding rows in
the database table.
Reviewed all uses of mBlockID, and of SqliteSampleBlock::GetBlockID() which
returns it, and of XML attribute "blockid" which persists it.
... Don't have special knowledge of "blockid" in ProjectSerializer, which should
be very low-level.
Instead, we can deserialize the project first, and use the block ids collected
by the sample block factory since f137a1e.
* Revert "AUP3: Don't delete sample blocks prematurely"
This reverts commit c1884349d5.
* "Don't delete sample blocks prematurely" fixed otherwise...
... and very simply.
Problem was that, only for an interactive effect (like Bass and Treble), the
save point was created, rolled back, created again, then committed.
But (unlike with the non-savepoint commands, even if savepoint is outermost),
rolling back a savepoint really just rewinds it without removing it -- therefore
the second savepoint was inner, but the first (outer) was never committed, so
some changes failed to persist.
Solution: add a commit after rollback of savepoint to implement destructor
of AutoCommitTransaction.
The reversion of c188434 also leaves AutoCommitTransaction as a better RAII
style operation. Rollback changes by default -- keep changes only if
success is explicitly indicated.
* Rename AutoCommitTransaction as TransactionScope...
... More appropriately, since it's now the rollback that is automatic but
the commit that must be explicit
Cliff reported that if you apply a macro to "Files" and you had
a "saved project" open at the time, you would get the "not saved
properly" dialog when you next open that "saved project".
This should correct it...
Several improvements in determining how much actual disk space a
sampleblock uses. This allows us to provide how much space will
be recovered when using File -> Compact Project.
In addition, the History window now provides better space estimates.
The first was due to a left over bit of code in Compact and has
been removed.
The second is in SaveProject. This one can't be removed, so a
progress dialog was added.
There's still the possibility if a crash happens at just the
right time that the project will be named "<project>_compact_back"
so we should probably look for it during startup.
This also changes all "Vacuum" references to "compact".
When doing a Save As, make sure autosave doc is removed
from the original project and the original project is
properly closed. (The original project does NOT get
compacted.)
The wrong sample blocks would be deleted at close in step 6:
1) New Project
2) Save and name
3) Import one stereo MP3 (about 6 minutes)
4) Save, close and re-open
5) Apply Bass and Treble to the track using real-time preview
6) Save, close and re-open
7) Message Failed to retrieve sample block
* Change usage of AutoCommitTransaction::Rollback...
... It is the more useful pattern (as in many finally blocks) for the failure
path in the destructor (which rolls back) to be the default, but an explicit
call must inform it of success.
This corrects the early return paths in Effect::DoEffect().
Throw inconsistency exception if Commit() is called again after having been
called once, successfully
Also remove a friend declaration
* UndoManager's interface uses consistent 0-based indexing of states...
... Returned by GetCurrentState() and used by SetStateTo(),
GetLongDescription(), GetShortDescription()
* SampleBlock::GetBlockID is const
* Generalized function to visit sample blocks used in a TrackList...
... Eliminating some duplication; put it in WaveTrack, not Track, to avoid
a dependency cycle.
* Eliminate more repetition with BlockSpaceUsageAccumulator
* Function to delete all blocks of/not-of a given set in one command
... It wasn't safe, on some platforms, because the sequence of destruction
of ProjectFileIO and ConnectionPtr is unspecified. It is safer that
ConnectionPtr just checks itself, not that ProjectFileIO fetches it again.
* DBConnection doesn't use ProjectFileIO or need friendship...
... Instead, it is given its own weak_ptr to the project
* Demote the bypass flag into DBConnection...
... So SqliteSampleBlock needs ProjectFileIO only to get the DBConnection
* Accessor functions for the connection objects for SqliteSampleBlock
* Another level of indirection to get to the DBConnection object...
... The document holds the unique_ptr to DBConnection in an attached object;
later we want the SqliteSampleBlockFactory to locate the same pointer without
using ProjectFileIO
* SqliteSampleBlock and its factory don't use class ProjectFileIO...
... Instead they share a pointer to the pointer to the current DBConnection.
This means they no longer know how to invoke the lazy opening of that
connection.
So just require that this be done before any operations on blocks happen. If
it hasn't, throw and let the application recover.
* ProjectFileIO no longer needs weak_ptr to Project for safety...
... so eliminate much ugliness from 127696879d
* Move DBConnection to new files...
... And SqliteSampleBlock does not depend on ProjectFileIO.
* SampleBlock.h doesn't need ClientData.h
* Function ProjectFileIO::Conn() isn't needed
SqliteSampleBlock now uses already prepared SQL statements for
all DB usage. This means that the statements won't have to be
compiled each time they are used.
* Fix typos in comments
* Correct the cleanup control flow in ProjectFileIO::SaveProject...
... so that it will not destroy the connection to the original database in
case CopyTo() the new file name fails.
* Fix uninitialized members of ProjectFileIO...
... which fixes this problem I observed:
Opening a previously saved project, saving-as to another path, then exiting
Audacity, gives a progress dialog waiting for checkpoints to end, which doesn't
go away
* Remove two mutexes...
... One wasn't used at all, and another was only ever used by one thread, and
then not correctly unlocked for each locking on all possible paths.
* Values that the worker thread writes and main reads should be atomic
* Remember to close db connections even after failure to open
* some comments
* No intermediate arrays (of arrays) of strings for query results...
... instead, let any query pass its own lambda to collect row data directly
however it needs to, for a bit of efficiency. Also the precautions of a new
GuardedCall
This is highly experimental. It's defers most checkpointing
to a separate thread to see if we get better throughput and
less choppiness when applying effects.
This reenables synchronous mode by default. However, for processing
where a power cut or crash can be tolerated, synchronous and journaling
are disabled. Once the processing is complete, they are reenabled.
Types of processing that are like this are "Save As", "Backup Project",
and "Vacuuming". They all write to a separate project file while
running, so the real project file is safe.
Unfortunately, effects are back to be slow and sluggish.
I believe I've address all of the weird file corruption issues and
I'll continue to continue testing for these.
Optimizes a couple of sample block copy loops by only preparing
the statement once outside the loop.
The connection configuration ensure that all connections use the same
settings...assuming you remember to configure it after opening. :-)
The possibly controversial setting is the "PRAGMA synchronous = off"