Audacity 3.2.0
ProjectFileIO.h
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5ProjectFileIO.h
6
7Paul Licameli split from AudacityProject.h
8
9**********************************************************************/
10
11#ifndef __AUDACITY_PROJECT_FILE_IO__
12#define __AUDACITY_PROJECT_FILE_IO__
13
14#include <memory>
15#include <optional>
16#include <unordered_set>
17
18#include <wx/event.h>
19
20#include "ClientData.h" // to inherit
21#include "Observer.h"
22#include "Prefs.h" // to inherit
23#include "XMLTagHandler.h" // to inherit
24
25struct sqlite3;
26struct sqlite3_context;
27struct sqlite3_stmt;
28struct sqlite3_value;
29
30class AudacityProject;
31class DBConnection;
35class TrackList;
36class WaveTrack;
37
38namespace BasicUI{ class WindowPlacement; }
39
40using WaveTrackArray = std::vector < std::shared_ptr < WaveTrack > >;
41
42// From SampleBlock.h
43using SampleBlockID = long long;
44
45using Connection = std::unique_ptr<DBConnection>;
46
47using BlockIDs = std::unordered_set<SampleBlockID>;
48
50enum class ProjectFileIOMessage : int {
55};
56
59class PROJECT_FILE_IO_API ProjectFileIO final
60 : public ClientData::Base
61 , public XMLTagHandler
62 , private PrefsListener
63 , public std::enable_shared_from_this<ProjectFileIO>
64 , public Observer::Publisher<ProjectFileIOMessage>
65{
66public:
69 struct PROJECT_FILE_IO_API TentativeConnection {
70 TentativeConnection(ProjectFileIO &projectFileIO);
74 void SetFileName(const FilePath &fileName);
75 void Commit();
76 private:
79 bool mCommitted{ false };
80 };
81
82 // Call this static function once before constructing any instances of this
83 // class. Reinvocations have no effect. Return value is true for success.
84 static bool InitializeSQL();
85
87 static const ProjectFileIO &Get( const AudacityProject &project );
88
90
91 ProjectFileIO( const ProjectFileIO & ) = delete;
94
95 const wxString &GetProjectTitle() const { return mTitle; }
96
97 // It seems odd to put this method in this class, but the results do depend
98 // on what is discovered while opening the file, such as whether it is a
99 // recovery file
100 void SetProjectTitle(int number = -1);
101
102 // Should be empty or a fully qualified file name
103 const FilePath &GetFileName() const;
104 void SetFileName( const FilePath &fileName );
105
106 bool IsModified() const;
107 bool IsTemporary() const;
108 bool IsRecovered() const;
109
110 bool AutoSave(bool recording = false);
111 bool AutoSaveDelete(sqlite3 *db = nullptr);
112
113 bool OpenProject();
114 bool CloseProject();
115 bool ReopenProject();
116
119 std::optional<TentativeConnection>
120 LoadProject(const FilePath &fileName, bool ignoreAutosave);
121
122 bool UpdateSaved(const TrackList *tracks = nullptr);
123 bool SaveProject(const FilePath &fileName, const TrackList *lastSaved);
124 bool SaveCopy(const FilePath& fileName);
125
126 wxLongLong GetFreeDiskSpace() const;
127
128 // Returns the bytes used for the given sample block
129 int64_t GetBlockUsage(SampleBlockID blockid);
130
131 // Returns the bytes used for all blocks owned by the given track list
132 int64_t GetCurrentUsage(
133 const std::vector<const TrackList*> &trackLists) const;
134
135 // Return the bytes used by all sample blocks in the project file, whether
136 // they are attached to the active tracks or held by the Undo manager.
137 int64_t GetTotalUsage();
138
139 // Return the bytes used for the given block using the connection to a
140 // specific database. This is the workhorse for the above 3 methods.
141 static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid);
142
143 // Displays an error dialog with a button that offers help
144 void ShowError(const BasicUI::WindowPlacement &placement,
145 const TranslatableString &dlogTitle,
146 const TranslatableString &message,
147 const wxString &helpPage);
148 const TranslatableString &GetLastError() const;
149 const TranslatableString &GetLibraryError() const;
150 int GetLastErrorCode() const;
151 const wxString &GetLastLog() const;
152
153 // Provides a means to bypass "DELETE"s at shutdown if the database
154 // is just going to be deleted anyway. This prevents a noticeable
155 // delay caused by SampleBlocks being deleted when the Sequences that
156 // own them are deleted.
157 //
158 // This is definitely hackage territory. While this ability would
159 // still be needed, I think handling it in a DB abstraction might be
160 // a tad bit cleaner.
161 //
162 // For it's usage, see:
163 // SqliteSampleBlock::~SqliteSampleBlock()
164 // ProjectManager::OnCloseWindow()
165 void SetBypass();
166
167private:
170 static const std::vector<wxString> &AuxiliaryFileSuffixes();
171
173 static FilePath SafetyFileName(const FilePath &src);
174
176
177 bool RenameOrWarn(const FilePath &src, const FilePath &dst);
178
179 bool MoveProject(const FilePath &src, const FilePath &dst);
180
181public:
183 static bool RemoveProject(const FilePath &filename);
184
185 // Object manages the temporary backing-up of project paths while
186 // trying to overwrite with new contents, and restoration in case of failure
187 class PROJECT_FILE_IO_API BackupProject {
188 public:
190 BackupProject( ProjectFileIO &projectFileIO, const FilePath &path );
192 bool IsOk() { return !mPath.empty(); }
194 void Discard();
197 private:
198 FilePath mPath, mSafety;
199 };
200
201 // Remove all unused space within a project file
202 void Compact(
203 const std::vector<const TrackList *> &tracks, bool force = false);
204
205 // The last compact check did actually compact the project file if true
206 bool WasCompacted();
207
208 // The last compact check found unused blocks in the project file
209 bool HadUnused();
210
211 // In one SQL command, delete sample blocks with ids in the given set, or
212 // (when complement is true), with ids not in the given set.
213 bool DeleteBlocks(const BlockIDs &blockids, bool complement);
214
215 // Type of function that is given the fields of one row and returns
216 // 0 for success or non-zero to stop the query
217 using ExecCB = std::function<int(int cols, char **vals, char **names)>;
218
220 bool HasConnection() const;
221
223 DBConnection &GetConnection();
224
226 wxString GenerateDoc();
227
228private:
229 void OnCheckpointFailure();
230
231 void WriteXMLHeader(XMLWriter &xmlFile) const;
232 void WriteXML(XMLWriter &xmlFile, bool recording = false,
233 const TrackList *tracks = nullptr) /* not override */;
234
235 // XMLTagHandler callback methods
236 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
237 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
238
239 void UpdatePrefs() override;
240
241 int Exec(const char *query, const ExecCB &callback, bool silent = false);
242
243 // The opening of the database may be delayed until demanded.
244 // Returns a non-null pointer to an open database, or throws an exception
245 // if opening fails.
246 sqlite3 *DB();
247
248 bool OpenConnection(FilePath fileName = {});
249 bool CloseConnection();
250
251 // Put the current database connection aside, keeping it open, so that
252 // another may be opened with OpenDB()
253 void SaveConnection();
254
255 // Close any set-aside connection
256 void DiscardConnection();
257
258 // Close any current connection and switch back to using the saved
259 void RestoreConnection();
260
261 // Use a connection that is already open rather than invoke OpenConnection
262 void UseConnection(Connection &&conn, const FilePath &filePath);
263
264 bool Query(const char *sql, const ExecCB &callback, bool silent = false);
265
266 bool GetValue(const char *sql, wxString &value, bool silent = false);
267 bool GetValue(const char *sql, int64_t &value, bool silent = false);
268
269 bool CheckVersion();
270 bool InstallSchema(sqlite3 *db, const char *schema = "main");
271
272 // Write project or autosave XML (binary) documents
273 bool WriteDoc(const char *table, const ProjectSerializer &autosave, const char *schema = "main");
274
275 // Application defined function to verify blockid exists is in set of blockids
276 static void InSet(sqlite3_context *context, int argc, sqlite3_value **argv);
277
278 // Return a database connection if successful, which caller must close
279 bool CopyTo(const FilePath &destpath,
280 const TranslatableString &msg,
281 bool isTemporary,
282 bool prune = false,
283 const std::vector<const TrackList *> &tracks = {}
287 );
288
290 void SetError(const TranslatableString & msg,
291 const TranslatableString& libraryError = {},
292 int errorCode = {});
293
295 void SetDBError(const TranslatableString & msg,
296 const TranslatableString& libraryError = {},
297 int errorCode = -1);
298
299 bool ShouldCompact(const std::vector<const TrackList *> &tracks);
300
301 // Gets values from SQLite B-tree structures
302 static unsigned int get2(const unsigned char *ptr);
303 static unsigned int get4(const unsigned char *ptr);
304 static int get_varint(const unsigned char *ptr, int64_t *out);
305
306private:
307 Connection &CurrConn();
308
309 // non-static data members
311
312 wxString mTitle;
313
314 std::shared_ptr<DBConnectionErrors> mpErrors;
315
316 // The project's file path
318
319 // Has this project been recovered from an auto-saved version
321
322 // Has this project been modified
324
325 // Is this project still a temporary/unsaved project
327
328 // Project was compacted last time Compact() ran
330
331 // Project had unused blocks during last Compact()
333
337};
338
340class PROJECT_FILE_IO_API InvisibleTemporaryProject
341{
342public:
346 {
347 return *mpProject;
348 }
349private:
350 std::shared_ptr<AudacityProject> mpProject;
351};
352
353#endif
Utility ClientData::Site to register hooks into a host class that attach client data.
std::unique_ptr< DBConnection > Connection
Definition: DBConnection.h:132
wxString FilePath
Definition: Project.h:21
std::vector< std::shared_ptr< WaveTrack > > WaveTrackArray
Definition: ProjectFileIO.h:40
std::unordered_set< SampleBlockID > BlockIDs
Definition: ProjectFileIO.h:47
ProjectFileIOMessage
Subscribe to ProjectFileIO to receive messages; always in idle time.
Definition: ProjectFileIO.h:50
@ CheckpointFailure
Failure happened in a worker thread.
@ ProjectTitleChange
A normal occurrence.
long long SampleBlockID
Definition: ProjectFileIO.h:43
static TranslatableStrings names
Definition: TagsEditor.cpp:153
const auto tracks
const auto project
std::vector< Attribute > AttributesList
Definition: XMLTagHandler.h:40
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Subclasses may hold information such as a parent window pointer for a dialog.
Definition: BasicUI.h:30
Makes a temporary project that doesn't display on the screen.
AudacityProject & Project()
std::shared_ptr< AudacityProject > mpProject
An object that sends messages to an open-ended list of subscribed callbacks.
Definition: Observer.h:108
A listener notified of changes in preferences.
Definition: Prefs.h:652
virtual void UpdatePrefs()=0
Definition: Prefs.cpp:154
bool IsOk()
Returns false if the renaming in the constructor failed.
Object associated with a project that manages reading and writing of Audacity project file formats,...
Definition: ProjectFileIO.h:65
ProjectFileIO & operator=(const ProjectFileIO &)=delete
AudacityProject & mProject
FilePath mFileName
const wxString & GetProjectTitle() const
Definition: ProjectFileIO.h:95
std::function< int(int cols, char **vals, char **names)> ExecCB
FilePath mPrevFileName
ProjectFileIO(const ProjectFileIO &)=delete
wxString mTitle
static unsigned int get2(const unsigned char *ptr)
Connection mPrevConn
std::shared_ptr< DBConnectionErrors > mpErrors
static int get_varint(const unsigned char *ptr, int64_t *out)
static unsigned int get4(const unsigned char *ptr)
a class used to (de)serialize the project catalog
Implementation of SampleBlock using Sqlite database.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:993
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:42
virtual XMLTagHandler * HandleXMLChild(const std::string_view &tag)=0
virtual bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs)=0
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:25
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
UTILITY_API const char *const * argv
A copy of argv; responsibility of application startup to assign it.
UTILITY_API int argc
A copy of argc; responsibility of application startup to assign it.
void SetError()
A convenient default parameter for class template Site.
Definition: ClientData.h:28
TentativeConnection(const TentativeConnection &other)=delete