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 <unordered_set>
16
17#include <wx/event.h>
18
19#include "ClientData.h" // to inherit
20#include "Prefs.h" // to inherit
21#include "XMLTagHandler.h" // to inherit
22
23struct sqlite3;
24struct sqlite3_context;
25struct sqlite3_stmt;
26struct sqlite3_value;
27
28class AudacityProject;
29class DBConnection;
33class TrackList;
34class WaveTrack;
35
36namespace BasicUI{ class WindowPlacement; }
37
38using WaveTrackArray = std::vector < std::shared_ptr < WaveTrack > >;
39
40// From SampleBlock.h
41using SampleBlockID = long long;
42
43using Connection = std::unique_ptr<DBConnection>;
44
45using BlockIDs = std::unordered_set<SampleBlockID>;
46
47// An event processed by the project in the main thread after a checkpoint
48// failure was detected in a worker thread
49wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
50 EVT_CHECKPOINT_FAILURE, wxCommandEvent );
51
52// An event processed by the project in the main thread after failure to
53// reconnect to the database, after temporary close and attempted file movement
54wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
55 EVT_RECONNECTION_FAILURE, wxCommandEvent );
56
59class AUDACITY_DLL_API ProjectFileIO final
60 : public ClientData::Base
61 , public XMLTagHandler
62 , private PrefsListener
63 , public std::enable_shared_from_this<ProjectFileIO>
64{
65public:
66 // Call this static function once before constructing any instances of this
67 // class. Reinvocations have no effect. Return value is true for success.
68 static bool InitializeSQL();
69
70 static ProjectFileIO &Get( AudacityProject &project );
71 static const ProjectFileIO &Get( const AudacityProject &project );
72
73 explicit ProjectFileIO( AudacityProject &project );
74
75 ProjectFileIO( const ProjectFileIO & ) PROHIBITED;
76 ProjectFileIO &operator=( const ProjectFileIO & ) PROHIBITED;
78
79 // It seems odd to put this method in this class, but the results do depend
80 // on what is discovered while opening the file, such as whether it is a
81 // recovery file
82 void SetProjectTitle(int number = -1);
83
84 // Should be empty or a fully qualified file name
85 const FilePath &GetFileName() const;
86 void SetFileName( const FilePath &fileName );
87
88 bool IsModified() const;
89 bool IsTemporary() const;
90 bool IsRecovered() const;
91
92 bool AutoSave(bool recording = false);
93 bool AutoSaveDelete(sqlite3 *db = nullptr);
94
95 bool OpenProject();
96 bool CloseProject();
97 bool ReopenProject();
98
99 bool LoadProject(const FilePath &fileName, bool ignoreAutosave);
100 bool UpdateSaved(const TrackList *tracks = nullptr);
101 bool SaveProject(const FilePath &fileName, const TrackList *lastSaved);
102 bool SaveCopy(const FilePath& fileName);
103
104 wxLongLong GetFreeDiskSpace() const;
105
106 // Returns the bytes used for the given sample block
107 int64_t GetBlockUsage(SampleBlockID blockid);
108
109 // Returns the bytes used for all blocks owned by the given track list
110 int64_t GetCurrentUsage(
111 const std::vector<const TrackList*> &trackLists) const;
112
113 // Return the bytes used by all sample blocks in the project file, whether
114 // they are attached to the active tracks or held by the Undo manager.
115 int64_t GetTotalUsage();
116
117 // Return the bytes used for the given block using the connection to a
118 // specific database. This is the workhorse for the above 3 methods.
119 static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid);
120
121 // Displays an error dialog with a button that offers help
122 void ShowError(const BasicUI::WindowPlacement &placement,
123 const TranslatableString &dlogTitle,
124 const TranslatableString &message,
125 const wxString &helpPage);
126 const TranslatableString &GetLastError() const;
127 const TranslatableString &GetLibraryError() const;
128 int GetLastErrorCode() const;
129 const wxString &GetLastLog() const;
130
131 // Provides a means to bypass "DELETE"s at shutdown if the database
132 // is just going to be deleted anyway. This prevents a noticeable
133 // delay caused by SampleBlocks being deleted when the Sequences that
134 // own them are deleted.
135 //
136 // This is definitely hackage territory. While this ability would
137 // still be needed, I think handling it in a DB abstraction might be
138 // a tad bit cleaner.
139 //
140 // For it's usage, see:
141 // SqliteSampleBlock::~SqliteSampleBlock()
142 // ProjectManager::OnCloseWindow()
143 void SetBypass();
144
145private:
148 static const std::vector<wxString> &AuxiliaryFileSuffixes();
149
151 static FilePath SafetyFileName(const FilePath &src);
152
154
155 bool RenameOrWarn(const FilePath &src, const FilePath &dst);
156
157 bool MoveProject(const FilePath &src, const FilePath &dst);
158
159public:
161 static bool RemoveProject(const FilePath &filename);
162
163 // Object manages the temporary backing-up of project paths while
164 // trying to overwrite with new contents, and restoration in case of failure
166 public:
168 BackupProject( ProjectFileIO &projectFileIO, const FilePath &path );
170 bool IsOk() { return !mPath.empty(); }
172 void Discard();
175 private:
176 FilePath mPath, mSafety;
177 };
178
179 // Remove all unused space within a project file
180 void Compact(
181 const std::vector<const TrackList *> &tracks, bool force = false);
182
183 // The last compact check did actually compact the project file if true
184 bool WasCompacted();
185
186 // The last compact check found unused blocks in the project file
187 bool HadUnused();
188
189 // In one SQL command, delete sample blocks with ids in the given set, or
190 // (when complement is true), with ids not in the given set.
191 bool DeleteBlocks(const BlockIDs &blockids, bool complement);
192
193 // Type of function that is given the fields of one row and returns
194 // 0 for success or non-zero to stop the query
195 using ExecCB = std::function<int(int cols, char **vals, char **names)>;
196
198 bool HasConnection() const;
199
201 DBConnection &GetConnection();
202
204 wxString GenerateDoc();
205
206private:
207 void OnCheckpointFailure();
208
209 void WriteXMLHeader(XMLWriter &xmlFile) const;
210 void WriteXML(XMLWriter &xmlFile, bool recording = false,
211 const TrackList *tracks = nullptr) /* not override */;
212
213 // XMLTagHandler callback methods
214 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
215 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
216
217 void UpdatePrefs() override;
218
219 int Exec(const char *query, const ExecCB &callback, bool silent = false);
220
221 // The opening of the database may be delayed until demanded.
222 // Returns a non-null pointer to an open database, or throws an exception
223 // if opening fails.
224 sqlite3 *DB();
225
226 bool OpenConnection(FilePath fileName = {});
227 bool CloseConnection();
228
229 // Put the current database connection aside, keeping it open, so that
230 // another may be opened with OpenDB()
231 void SaveConnection();
232
233 // Close any set-aside connection
234 void DiscardConnection();
235
236 // Close any current connection and switch back to using the saved
237 void RestoreConnection();
238
239 // Use a connection that is already open rather than invoke OpenConnection
240 void UseConnection(Connection &&conn, const FilePath &filePath);
241
242 bool Query(const char *sql, const ExecCB &callback, bool silent = false);
243
244 bool GetValue(const char *sql, wxString &value, bool silent = false);
245 bool GetValue(const char *sql, int64_t &value, bool silent = false);
246
247 bool CheckVersion();
248 bool InstallSchema(sqlite3 *db, const char *schema = "main");
249
250 // Write project or autosave XML (binary) documents
251 bool WriteDoc(const char *table, const ProjectSerializer &autosave, const char *schema = "main");
252
253 // Application defined function to verify blockid exists is in set of blockids
254 static void InSet(sqlite3_context *context, int argc, sqlite3_value **argv);
255
256 // Return a database connection if successful, which caller must close
257 bool CopyTo(const FilePath &destpath,
258 const TranslatableString &msg,
259 bool isTemporary,
260 bool prune = false,
261 const std::vector<const TrackList *> &tracks = {}
265 );
266
268 void SetError(const TranslatableString & msg,
269 const TranslatableString& libraryError = {},
270 int errorCode = {});
271
273 void SetDBError(const TranslatableString & msg,
274 const TranslatableString& libraryError = {},
275 int errorCode = -1);
276
277 bool ShouldCompact(const std::vector<const TrackList *> &tracks);
278
279 // Gets values from SQLite B-tree structures
280 static unsigned int get2(const unsigned char *ptr);
281 static unsigned int get4(const unsigned char *ptr);
282 static int get_varint(const unsigned char *ptr, int64_t *out);
283
284private:
285 Connection &CurrConn();
286
287 // non-static data members
289
290 std::shared_ptr<DBConnectionErrors> mpErrors;
291
292 // The project's file path
294
295 // Has this project been recovered from an auto-saved version
297
298 // Has this project been modified
300
301 // Is this project still a temporary/unsaved project
303
304 // Project was compacted last time Compact() ran
306
307 // Project had unused blocks during last Compact()
309
313};
314
315class wxTopLevelWindow;
316
317// TitleRestorer restores project window titles to what they were, in its destructor.
319public:
320 TitleRestorer( wxTopLevelWindow &window, AudacityProject &project );
322 wxString sProjNumber;
323 wxString sProjName;
325};
326
327// This event is emitted by the project when there is a change
328// in its title
330 EVT_PROJECT_TITLE_CHANGE, wxCommandEvent);
331
333class AUDACITY_DLL_API InvisibleTemporaryProject
334{
335public:
339 {
340 return *mpProject;
341 }
342private:
343 std::shared_ptr<AudacityProject> mpProject;
344};
345
346#endif
std::vector< std::shared_ptr< WaveTrack > > WaveTrackArray
Definition: AudioIO.h:49
Utility ClientData::Site to register hooks into a host class that attach client data.
std::unique_ptr< DBConnection > Connection
Definition: DBConnection.h:130
wxString FilePath
Definition: Project.h:20
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_CHECKPOINT_FAILURE, wxCommandEvent)
std::unordered_set< SampleBlockID > BlockIDs
Definition: ProjectFileIO.h:45
long long SampleBlockID
Definition: ProjectFileIO.h:41
static TranslatableStrings names
Definition: TagsEditor.cpp:151
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:89
Subclasses may hold information such as a parent window pointer for a dialog.
Definition: BasicUI.h:29
Makes a temporary project that doesn't display on the screen.
AudacityProject & Project()
std::shared_ptr< AudacityProject > mpProject
A listener notified of changes in preferences.
Definition: Prefs.h:543
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:64
AudacityProject & mProject
ProjectFileIO(const ProjectFileIO &) PROHIBITED
FilePath mFileName
std::function< int(int cols, char **vals, char **names)> ExecCB
ProjectFileIO & operator=(const ProjectFileIO &) PROHIBITED
FilePath mPrevFileName
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.
size_t UnnamedCount
TitleRestorer(wxTopLevelWindow &window, AudacityProject &project)
wxString sProjName
wxString sProjNumber
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1330
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
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:26
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:26
void SetError()
AUDACITY_DLL_API void UpdatePrefs(wxWindow *pParent)
A convenient default parameter for class template Site.
Definition: ClientData.h:28