11namespace tracktion {
inline namespace engine
17 :
Thread (
"TemporyFileWriter") {}
28 TRACKTION_ASSERT_MESSAGE_THREAD
36 TRACKTION_ASSERT_MESSAGE_THREAD
60 item.
first.writeToStream (os);
84 EditFileOperations::getTempVersionOfEditFile (item->getSourceFile()).deleteFile();
89 editSnapshot->refreshFromProjectManager();
101 for (
auto& ptr : sharedData)
102 if (&ptr->edit == &edit)
106 sharedData.push_back (newData);
112 for (
auto& ptr : sharedData)
118 sharedData.erase (
std::remove_if (sharedData.begin(), sharedData.end(),
119 [] (
auto& ptr) { return ptr.use_count() == 1; }),
132 : data (cache->get (e))
145 editFileWriter->writeTreeToFile (std::move (v), f);
155EditFileOperations::EditFileOperations (
Edit& e)
156 : edit (e), state (edit.state),
158 timeOfLastSave (sharedDataPimpl->data->timeOfLastSave),
159 editSnapshot (sharedDataPimpl->data->editSnapshot)
163EditFileOperations::~EditFileOperations()
167juce::File EditFileOperations::getEditFile()
const
172bool EditFileOperations::writeToFile (
const juce::File& file,
bool writeQuickBinaryVersion)
178 if (! writeQuickBinaryVersion)
180 EditPlaybackContext::RealtimePriorityDisabler realtimeDisabler (edit.
engine);
182 sharedDataPimpl->editFileWriter->flushAllFiles();
185 if (file.hasWriteAccess() && ! file.isDirectory())
187 if (writeQuickBinaryVersion)
195 if (editSnapshot !=
nullptr)
199 ok = xml->writeTo (file);
211static bool editSaveError (Edit& edit,
const juce::File& file,
bool warnOfFailure)
214 TRACKTION_LOG_ERROR (
"Can't write to edit file: " + file.getFullPathName());
219 .replace (
"XEDTX", edit.getName())
220 .replace (
"XFNX", file.getFullPathName()));
222 if (! file.hasWriteAccess())
223 s <<
"\n\n(" <<
TRANS(
"File or directory is read-only") <<
")";
225 return edit.engine.getUIBehaviour().showOkCancelAlertBox (
TRANS(
"Save edit"), s,
226 TRANS(
"Carry on anyway"));
232bool EditFileOperations::save (
bool warnOfFailure,
233 bool forceSaveEvenIfNotModified,
234 bool offerToDiscardChanges)
237 auto editFile = getEditFile();
243 edit.getParameterControlMappings().saveToEdit();
245 auto tempFile = getTempVersionFile();
247 if (! saveTempVersion (
true))
248 return editSaveError (edit, tempFile, warnOfFailure);
250 if (forceSaveEvenIfNotModified || edit.hasChangedSinceSaved())
254 proj->Selectable::changed();
256 if (offerToDiscardChanges)
258 const int r = edit.engine.getUIBehaviour().showYesNoCancelAlertBox (
TRANS(
"Closing Edit"),
259 TRANS(
"Do you want to save your changes to \"XNMX\" before closing it?")
260 .replace (
"XNMX", edit.getName()),
262 TRANS(
"Discard changes"));
266 tempFile.deleteFile();
271 if (editSnapshot !=
nullptr)
272 editSnapshot->refreshCacheAndNotifyListeners();
274 if (! tempFile.moveFileTo (editFile))
275 return editSaveError (edit, editFile, warnOfFailure);
277 edit.engine.getEngineBehaviour().editHasBeenSaved (edit, editFile);
280 tempFile.deleteFile();
283 item->setLength (edit.getLength().inSeconds());
285 edit.resetChangedStatus();
289bool EditFileOperations::saveAs()
291 #if JUCE_MODAL_LOOPS_PERMITTED
293 auto newEditName = getNonExistentSiblingWithIncrementedNumberSuffix (getEditFile(),
false);
299 if (chooser.browseForFileToSave (
false))
300 return saveAs (chooser.getResult().withFileExtension (editFileSuffix));
306bool EditFileOperations::saveAs (
const juce::File& f,
bool forceOverwriteExisting)
308 if (f == getEditFile())
309 return save (
true,
false,
false);
313 if (! edit.engine.getUIBehaviour().showOkCancelAlertBox (
TRANS(
"Save Edit") +
"...",
314 TRANS(
"The file XFNX already exists. Do you want to overwrite it?")
326 if (
auto newItem = project->createNewItem (f, item->getType(),
328 item->getDescription(),
332 auto oldTempFile = getTempVersionFile();
334 newItem->copyAllPropertiesFrom (*item);
337 jassert (edit.getProjectItemID() != newItem->getID());
338 edit.setProjectItemID (newItem->getID());
339 editSnapshot = EditSnapshot::getEditSnapshot (edit.engine, edit.getProjectItemID());
341 const bool ok = save (
true,
true,
false);
344 oldTempFile.deleteFile();
346 edit.sendSourceFileUpdate();
357 edit.getParameterControlMappings().saveToEdit();
359 auto tempFile = getTempVersionFile();
361 if (! saveTempVersion (
true))
362 return editSaveError (edit, tempFile,
true);
364 if (editSnapshot !=
nullptr)
365 editSnapshot->refreshCacheAndNotifyListeners();
370 if (! tempFile.moveFileTo (f))
371 return editSaveError (edit, f,
true);
373 tempFile.deleteFile();
375 edit.resetChangedStatus();
376 edit.engine.getEngineBehaviour().editHasBeenSaved (edit, f);
385bool EditFileOperations::saveTempVersion (
bool forceSaveEvenIfUnchanged)
389 if (! (forceSaveEvenIfUnchanged || edit.hasChangedSinceSaved()))
392 return writeToFile (getTempVersionFile(), ! forceSaveEvenIfUnchanged);
401juce::File EditFileOperations::getTempVersionFile()
const
403 return getTempVersionOfEditFile (getEditFile());
406void EditFileOperations::deleteTempVersion()
412void EditFileOperations::updateEditFiles()
439 state = juce::ValueTree::fromXml (*xml);
446 if (state = juce::ValueTree::readFromStream (is); state.hasType (IDs::EDIT))
460 state.setProperty (IDs::appVersion, e.
getPropertyStorage().getApplicationVersion(),
nullptr);
463 state.setProperty (IDs::projectID, itemID.toString(),
nullptr);
477 if (! editState.isValid())
480 auto id = ProjectItemID::fromProperty (editState, IDs::projectID);
493 [editFile] {
return editFile; },
510 [editFile] {
return editFile; },
bool isEmpty() const noexcept
void add(const ElementType &newElement)
ElementType removeAndReturn(int indexToRemove)
bool existsAsFile() const
const String & getFullPathName() const noexcept
File getSiblingFile(StringRef siblingFileName) const
String getFileNameWithoutExtension() const
bool isValid() const noexcept
Thread(const String &threadName, size_t threadStackSize=osDefaultStackSize)
bool threadShouldExit() const
bool stopThread(int timeOutMilliseconds)
static Time JUCE_CALLTYPE getCurrentTime() noexcept
std::unique_ptr< XmlElement > createXml() const
ValueTree createCopy() const
bool wait(double timeOutMilliseconds=-1.0) const
static void saveAllSettings(Engine &engine)
Saves the settings of all open custom surfaces.
The Tracktion Edit class!
static std::unique_ptr< Edit > createEdit(Options)
Creates an Edit for the given options.
juce::ValueTree state
The ValueTree of the Edit state.
std::function< juce::File()> editFileRetriever
This callback can be set to return the file for this Edit.
EditRole
Enum used to determine what an Edit is being used for.
@ forEditing
Creates an Edit for normal use.
TimeDuration getLength() const
Returns the end time of last clip.
void flushState()
Saves the plugin, automap and ARA states to the state ValueTree.
static std::unique_ptr< Edit > createEditForExamining(Engine &, juce::ValueTree, EditRole role=EditRole::forExamining)
Creates an Edit that loads a state, using the role Edit::forExamining.
ProjectItemID getProjectItemID() const noexcept
Returns the ProjectItemID of the Edit.
static int getDefaultNumUndoLevels() noexcept
Returns the default number of undo levels that should be used.
Engine & engine
A reference to the Engine.
The Engine is the central class for all tracktion sessions.
PropertyStorage & getPropertyStorage() const
Returns the PropertyStorage user settings customisable XML file.
An ID representing one of the items in a Project.
static ProjectItemID createNewID(int projectID) noexcept
Generates a new ID for a given project.
ProjectItem::Ptr getProjectItem(ProjectItemID)
tries to find the project that contains an id, and open it as a ProjectItem.
static bool isSelectableValid(const Selectable *) noexcept
checks whether this object has been deleted.
#define TRANS(stringLiteral)
std::unique_ptr< XmlElement > parseXML(const String &textToParse)
std::unique_ptr< Edit > loadEditForExamining(ProjectManager &pm, ProjectItemID itemID, Edit::EditRole role)
Uses the ProjectManager to find an Edit file and open it.
juce::ValueTree loadEditFromProjectManager(ProjectManager &pm, ProjectItemID itemID)
Uses the ProjectManager to find an Edit file and load it as a ValueTree.
juce::ValueTree loadEditFromFile(Engine &e, const juce::File &f, ProjectItemID itemID)
Legacy, will be deprecated soon.
ProjectItem::Ptr getProjectItemForEdit(const Edit &e)
Tries to find the project item that refers to this edit (but may return nullptr!)
Project::Ptr getProjectForEdit(const Edit &e)
Tries to find the project that contains this edit (but may return nullptr!)
juce::ValueTree createEmptyEdit(Engine &e)
Legacy, will be deprecated soon.
juce::ValueTree updateLegacyEdit(const juce::ValueTree &)
Converts old edit formats to the latest structure.
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.