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 "Observer.h"
21#include "Prefs.h" // to inherit
22#include "XMLTagHandler.h" // to inherit
23
24struct sqlite3;
25struct sqlite3_context;
26struct sqlite3_stmt;
27struct sqlite3_value;
28
29class AudacityProject;
30class DBConnection;
34class TrackList;
35class WaveTrack;
36
37namespace BasicUI{ class WindowPlacement; }
38
39using WaveTrackArray = std::vector < std::shared_ptr < WaveTrack > >;
40
41// From SampleBlock.h
42using SampleBlockID = long long;
43
44using Connection = std::unique_ptr<DBConnection>;
45
46using BlockIDs = std::unordered_set<SampleBlockID>;
47
49enum class ProjectFileIOMessage : int {
54};
55
58class PROJECT_FILE_IO_API ProjectFileIO final
59 : public ClientData::Base
60 , public XMLTagHandler
61 , private PrefsListener
62 , public std::enable_shared_from_this<ProjectFileIO>
63 , public Observer::Publisher<ProjectFileIOMessage>
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 & ) = delete;
78
79 const wxString &GetProjectTitle() const { return mTitle; }
80
81 // It seems odd to put this method in this class, but the results do depend
82 // on what is discovered while opening the file, such as whether it is a
83 // recovery file
84 void SetProjectTitle(int number = -1);
85
86 // Should be empty or a fully qualified file name
87 const FilePath &GetFileName() const;
88 void SetFileName( const FilePath &fileName );
89
90 bool IsModified() const;
91 bool IsTemporary() const;
92 bool IsRecovered() const;
93
94 bool AutoSave(bool recording = false);
95 bool AutoSaveDelete(sqlite3 *db = nullptr);
96
97 bool OpenProject();
98 bool CloseProject();
99 bool ReopenProject();
100
101 bool LoadProject(const FilePath &fileName, bool ignoreAutosave);
102 bool UpdateSaved(const TrackList *tracks = nullptr);
103 bool SaveProject(const FilePath &fileName, const TrackList *lastSaved);
104 bool SaveCopy(const FilePath& fileName);
105
106 wxLongLong GetFreeDiskSpace() const;
107
108 // Returns the bytes used for the given sample block
109 int64_t GetBlockUsage(SampleBlockID blockid);
110
111 // Returns the bytes used for all blocks owned by the given track list
112 int64_t GetCurrentUsage(
113 const std::vector<const TrackList*> &trackLists) const;
114
115 // Return the bytes used by all sample blocks in the project file, whether
116 // they are attached to the active tracks or held by the Undo manager.
117 int64_t GetTotalUsage();
118
119 // Return the bytes used for the given block using the connection to a
120 // specific database. This is the workhorse for the above 3 methods.
121 static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid);
122
123 // Displays an error dialog with a button that offers help
124 void ShowError(const BasicUI::WindowPlacement &placement,
125 const TranslatableString &dlogTitle,
126 const TranslatableString &message,
127 const wxString &helpPage);
128 const TranslatableString &GetLastError() const;
129 const TranslatableString &GetLibraryError() const;
130 int GetLastErrorCode() const;
131 const wxString &GetLastLog() const;
132
133 // Provides a means to bypass "DELETE"s at shutdown if the database
134 // is just going to be deleted anyway. This prevents a noticeable
135 // delay caused by SampleBlocks being deleted when the Sequences that
136 // own them are deleted.
137 //
138 // This is definitely hackage territory. While this ability would
139 // still be needed, I think handling it in a DB abstraction might be
140 // a tad bit cleaner.
141 //
142 // For it's usage, see:
143 // SqliteSampleBlock::~SqliteSampleBlock()
144 // ProjectManager::OnCloseWindow()
145 void SetBypass();
146
147private:
150 static const std::vector<wxString> &AuxiliaryFileSuffixes();
151
153 static FilePath SafetyFileName(const FilePath &src);
154
156
157 bool RenameOrWarn(const FilePath &src, const FilePath &dst);
158
159 bool MoveProject(const FilePath &src, const FilePath &dst);
160
161public:
163 static bool RemoveProject(const FilePath &filename);
164
165 // Object manages the temporary backing-up of project paths while
166 // trying to overwrite with new contents, and restoration in case of failure
167 class PROJECT_FILE_IO_API BackupProject {
168 public:
170 BackupProject( ProjectFileIO &projectFileIO, const FilePath &path );
172 bool IsOk() { return !mPath.empty(); }
174 void Discard();
177 private:
178 FilePath mPath, mSafety;
179 };
180
181 // Remove all unused space within a project file
182 void Compact(
183 const std::vector<const TrackList *> &tracks, bool force = false);
184
185 // The last compact check did actually compact the project file if true
186 bool WasCompacted();
187
188 // The last compact check found unused blocks in the project file
189 bool HadUnused();
190
191 // In one SQL command, delete sample blocks with ids in the given set, or
192 // (when complement is true), with ids not in the given set.
193 bool DeleteBlocks(const BlockIDs &blockids, bool complement);
194
195 // Type of function that is given the fields of one row and returns
196 // 0 for success or non-zero to stop the query
197 using ExecCB = std::function<int(int cols, char **vals, char **names)>;
198
200 bool HasConnection() const;
201
203 DBConnection &GetConnection();
204
206 wxString GenerateDoc();
207
208private:
209 void OnCheckpointFailure();
210
211 void WriteXMLHeader(XMLWriter &xmlFile) const;
212 void WriteXML(XMLWriter &xmlFile, bool recording = false,
213 const TrackList *tracks = nullptr) /* not override */;
214
215 // XMLTagHandler callback methods
216 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
217 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
218
219 void UpdatePrefs() override;
220
221 int Exec(const char *query, const ExecCB &callback, bool silent = false);
222
223 // The opening of the database may be delayed until demanded.
224 // Returns a non-null pointer to an open database, or throws an exception
225 // if opening fails.
226 sqlite3 *DB();
227
228 bool OpenConnection(FilePath fileName = {});
229 bool CloseConnection();
230
231 // Put the current database connection aside, keeping it open, so that
232 // another may be opened with OpenDB()
233 void SaveConnection();
234
235 // Close any set-aside connection
236 void DiscardConnection();
237
238 // Close any current connection and switch back to using the saved
239 void RestoreConnection();
240
241 // Use a connection that is already open rather than invoke OpenConnection
242 void UseConnection(Connection &&conn, const FilePath &filePath);
243
244 bool Query(const char *sql, const ExecCB &callback, bool silent = false);
245
246 bool GetValue(const char *sql, wxString &value, bool silent = false);
247 bool GetValue(const char *sql, int64_t &value, bool silent = false);
248
249 bool CheckVersion();
250 bool InstallSchema(sqlite3 *db, const char *schema = "main");
251
252 // Write project or autosave XML (binary) documents
253 bool WriteDoc(const char *table, const ProjectSerializer &autosave, const char *schema = "main");
254
255 // Application defined function to verify blockid exists is in set of blockids
256 static void InSet(sqlite3_context *context, int argc, sqlite3_value **argv);
257
258 // Return a database connection if successful, which caller must close
259 bool CopyTo(const FilePath &destpath,
260 const TranslatableString &msg,
261 bool isTemporary,
262 bool prune = false,
263 const std::vector<const TrackList *> &tracks = {}
267 );
268
270 void SetError(const TranslatableString & msg,
271 const TranslatableString& libraryError = {},
272 int errorCode = {});
273
275 void SetDBError(const TranslatableString & msg,
276 const TranslatableString& libraryError = {},
277 int errorCode = -1);
278
279 bool ShouldCompact(const std::vector<const TrackList *> &tracks);
280
281 // Gets values from SQLite B-tree structures
282 static unsigned int get2(const unsigned char *ptr);
283 static unsigned int get4(const unsigned char *ptr);
284 static int get_varint(const unsigned char *ptr, int64_t *out);
285
286private:
287 Connection &CurrConn();
288
289 // non-static data members
291
292 wxString mTitle;
293
294 std::shared_ptr<DBConnectionErrors> mpErrors;
295
296 // The project's file path
298
299 // Has this project been recovered from an auto-saved version
301
302 // Has this project been modified
304
305 // Is this project still a temporary/unsaved project
307
308 // Project was compacted last time Compact() ran
310
311 // Project had unused blocks during last Compact()
313
317};
318
320class PROJECT_FILE_IO_API InvisibleTemporaryProject
321{
322public:
326 {
327 return *mpProject;
328 }
329private:
330 std::shared_ptr<AudacityProject> mpProject;
331};
332
333#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::unordered_set< SampleBlockID > BlockIDs
Definition: ProjectFileIO.h:46
ProjectFileIOMessage
Subscribe to ProjectFileIO to receive messages; always in idle time.
Definition: ProjectFileIO.h:49
@ CheckpointFailure
Failure happened in a worker thread.
@ ProjectTitleChange
A normal occurrence.
long long SampleBlockID
Definition: ProjectFileIO.h:42
std::vector< std::shared_ptr< WaveTrack > > WaveTrackArray
static TranslatableStrings names
Definition: TagsEditor.cpp:152
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:29
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:556
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
ProjectFileIO & operator=(const ProjectFileIO &)=delete
AudacityProject & mProject
FilePath mFileName
const wxString & GetProjectTitle() const
Definition: ProjectFileIO.h:79
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:1201
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:51
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()
AUDACITY_DLL_API void UpdatePrefs(wxWindow *pParent)
A convenient default parameter for class template Site.
Definition: ClientData.h:28