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