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 {
56};
57
60class PROJECT_FILE_IO_API ProjectFileIO final
61 : public ClientData::Base
62 , public XMLTagHandler
63 , private PrefsListener
64 , public std::enable_shared_from_this<ProjectFileIO>
65 , public Observer::Publisher<ProjectFileIOMessage>
66{
67public:
70 struct PROJECT_FILE_IO_API TentativeConnection {
71 TentativeConnection(ProjectFileIO &projectFileIO);
75 void SetFileName(const FilePath &fileName);
76 void Commit();
77 private:
80 bool mCommitted{ false };
81 };
82
83 // Call this static function once before constructing any instances of this
84 // class. Reinvocations have no effect. Return value is true for success.
85 static bool InitializeSQL();
86
88 static const ProjectFileIO &Get( const AudacityProject &project );
89
91
92 ProjectFileIO( const ProjectFileIO & ) = delete;
95
96 const wxString &GetProjectTitle() const { return mTitle; }
97
98 // It seems odd to put this method in this class, but the results do depend
99 // on what is discovered while opening the file, such as whether it is a
100 // recovery file
101 void SetProjectTitle(int number = -1);
102
103 // Should be empty or a fully qualified file name
104 const FilePath &GetFileName() const;
105 void SetFileName( const FilePath &fileName );
106
107 bool IsModified() const;
108 bool IsTemporary() const;
109 bool IsRecovered() const;
110
111 void MarkTemporary();
112
113 bool AutoSave(bool recording = false);
114 bool AutoSaveDelete(sqlite3 *db = nullptr);
115
116 bool OpenProject();
117 void CloseProject();
118 bool ReopenProject();
119
122 std::optional<TentativeConnection>
123 LoadProject(const FilePath &fileName, bool ignoreAutosave);
124
125 bool UpdateSaved(const TrackList *tracks = nullptr);
126 bool SaveProject(const FilePath &fileName, const TrackList *lastSaved);
127 bool SaveCopy(const FilePath& fileName);
128
129 wxLongLong GetFreeDiskSpace() const;
130
131 // Returns the bytes used for the given sample block
132 int64_t GetBlockUsage(SampleBlockID blockid);
133
134 // Returns the bytes used for all blocks owned by the given track list
135 int64_t GetCurrentUsage(
136 const std::vector<const TrackList*> &trackLists) const;
137
138 // Return the bytes used by all sample blocks in the project file, whether
139 // they are attached to the active tracks or held by the Undo manager.
140 int64_t GetTotalUsage();
141
142 // Return the bytes used for the given block using the connection to a
143 // specific database. This is the workhorse for the above 3 methods.
144 static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid);
145
146 // Displays an error dialog with a button that offers help
147 void ShowError(const BasicUI::WindowPlacement &placement,
148 const TranslatableString &dlogTitle,
149 const TranslatableString &message,
150 const wxString &helpPage);
151 const TranslatableString &GetLastError() const;
152 const TranslatableString &GetLibraryError() const;
153 int GetLastErrorCode() const;
154 const wxString &GetLastLog() const;
155
156 // Provides a means to bypass "DELETE"s at shutdown if the database
157 // is just going to be deleted anyway. This prevents a noticeable
158 // delay caused by SampleBlocks being deleted when the Sequences that
159 // own them are deleted.
160 //
161 // This is definitely hackage territory. While this ability would
162 // still be needed, I think handling it in a DB abstraction might be
163 // a tad bit cleaner.
164 //
165 // For it's usage, see:
166 // SqliteSampleBlock::~SqliteSampleBlock()
167 // ProjectManager::OnCloseWindow()
168 void SetBypass();
169
170private:
173 static const std::vector<wxString> &AuxiliaryFileSuffixes();
174
176 static FilePath SafetyFileName(const FilePath &src);
177
179
180 bool RenameOrWarn(const FilePath &src, const FilePath &dst);
181
182 bool MoveProject(const FilePath &src, const FilePath &dst);
183
184public:
186 static bool RemoveProject(const FilePath &filename);
187
188 // Object manages the temporary backing-up of project paths while
189 // trying to overwrite with new contents, and restoration in case of failure
190 class PROJECT_FILE_IO_API BackupProject {
191 public:
193 BackupProject( ProjectFileIO &projectFileIO, const FilePath &path );
195 bool IsOk() { return !mPath.empty(); }
197 void Discard();
200 private:
201 FilePath mPath, mSafety;
202 };
203
204 // Remove all unused space within a project file
205 void Compact(
206 const std::vector<const TrackList *> &tracks, bool force = false);
207
208 // The last compact check did actually compact the project file if true
209 bool WasCompacted();
210
211 // The last compact check found unused blocks in the project file
212 bool HadUnused();
213
214 // In one SQL command, delete sample blocks with ids in the given set, or
215 // (when complement is true), with ids not in the given set.
216 bool DeleteBlocks(const BlockIDs &blockids, bool complement);
217
218 // Type of function that is given the fields of one row and returns
219 // 0 for success or non-zero to stop the query
220 using ExecCB = std::function<int(int cols, char **vals, char **names)>;
221
223 bool HasConnection() const;
224
226 DBConnection &GetConnection();
227
229 wxString GenerateDoc();
230
231private:
232 void OnCheckpointFailure();
233
234 void WriteXMLHeader(XMLWriter &xmlFile) const;
235 void WriteXML(XMLWriter &xmlFile, bool recording = false,
236 const TrackList *tracks = nullptr) /* not override */;
237
238 // XMLTagHandler callback methods
239 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
240 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
241
242 void UpdatePrefs() override;
243
244 int Exec(const char *query, const ExecCB &callback, bool silent = false);
245
246 // The opening of the database may be delayed until demanded.
247 // Returns a non-null pointer to an open database, or throws an exception
248 // if opening fails.
249 sqlite3 *DB();
250
251 bool OpenConnection(FilePath fileName = {});
252 bool CloseConnection();
253
254 // Put the current database connection aside, keeping it open, so that
255 // another may be opened with OpenDB()
256 void SaveConnection();
257
258 // Close any set-aside connection
259 void DiscardConnection();
260
261 // Close any current connection and switch back to using the saved
262 void RestoreConnection();
263
264 // Use a connection that is already open rather than invoke OpenConnection
265 void UseConnection(Connection &&conn, const FilePath &filePath);
266
267 bool Query(const char *sql, const ExecCB &callback, bool silent = false);
268
269 bool GetValue(const char *sql, wxString &value, bool silent = false);
270 bool GetValue(const char *sql, int64_t &value, bool silent = false);
271
272 bool CheckVersion();
273 bool InstallSchema(sqlite3 *db, const char *schema = "main");
274
275 // Write project or autosave XML (binary) documents
276 bool WriteDoc(const char *table, const ProjectSerializer &autosave, const char *schema = "main");
277
278 // Application defined function to verify blockid exists is in set of blockids
279 static void InSet(sqlite3_context *context, int argc, sqlite3_value **argv);
280
281 // Return a database connection if successful, which caller must close
282 bool CopyTo(const FilePath &destpath,
283 const TranslatableString &msg,
284 bool isTemporary,
285 bool prune = false,
286 const std::vector<const TrackList *> &tracks = {}
290 );
291
293 void SetError(const TranslatableString & msg,
294 const TranslatableString& libraryError = {},
295 int errorCode = {});
296
298 void SetDBError(const TranslatableString & msg,
299 const TranslatableString& libraryError = {},
300 int errorCode = -1);
301
302 bool ShouldCompact(const std::vector<const TrackList *> &tracks);
303
304private:
305 Connection &CurrConn();
306
307 // non-static data members
309
310 wxString mTitle;
311
312 std::shared_ptr<DBConnectionErrors> mpErrors;
313
314 // The project's file path
316
317 // Has this project been recovered from an auto-saved version
319
320 // Has this project been modified
322
323 // Is this project still a temporary/unsaved project
325
326 // Project was compacted last time Compact() ran
328
329 // Project had unused blocks during last Compact()
331
335};
336
338class PROJECT_FILE_IO_API InvisibleTemporaryProject
339{
340public:
344 {
345 return *mpProject;
346 }
347private:
348 std::shared_ptr<AudacityProject> mpProject;
349};
350
351#endif
Utility ClientData::Site to register hooks into a host class that attach client data.
long long SampleBlockID
Definition: CloudSyncDTO.h:26
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.
@ ProjectFilePathChange
A normal occurrence.
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:66
ProjectFileIO & operator=(const ProjectFileIO &)=delete
AudacityProject & mProject
FilePath mFileName
const wxString & GetProjectTitle() const
Definition: ProjectFileIO.h:96
std::function< int(int cols, char **vals, char **names)> ExecCB
FilePath mPrevFileName
ProjectFileIO(const ProjectFileIO &)=delete
wxString mTitle
Connection mPrevConn
std::shared_ptr< DBConnectionErrors > mpErrors
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:850
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
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:201
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()
void ReopenProject(AudacityProject &project)
A convenient default parameter for class template Site.
Definition: ClientData.h:29
TentativeConnection(const TentativeConnection &other)=delete