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