26 if (
auto xml = v.createXml())
29 return juce::ValueTree::fromXml (*xml);
39 updateV2TempoData (editXML);
40 convertV2Markers (editXML);
41 convertVideo (editXML);
42 convertOldView (editXML);
43 convertV9PitchSequence (editXML);
44 convertV9Markers (editXML);
45 convertMidiVersion (editXML);
46 convertMpeVersion (editXML);
47 convertPluginsAndClips (editXML);
48 fixTrackTags (editXML);
49 convertFolderTracks (editXML);
50 convertLegacyLFOs (editXML);
51 convertLegacyIDsIfNeeded (editXML);
82 static void convertSequenceMidiVersion (
juce::XmlElement& xml,
double timeToBeatFactor)
86 if (seq->getIntAttribute (IDs::ver, 0) < 1)
88 for (
auto e : seq->getChildIterator())
115 convertSequenceMidiVersion (*e, timeToBeatFactor);
121 for (
auto note : seq->getChildWithTagNameIterator (IDs::NOTE))
123 if (
auto na = note->getChildByName (IDs::NA))
125 if (
auto* naseq = na->getChildByName (
"MIDISEQUENCE"))
128 if (naseq->getBoolAttribute (IDs::converted,
false))
131 naseq->setAttribute (IDs::converted,
true);
133 for (
auto control : naseq->getChildWithTagNameIterator (IDs::CONTROL))
136 if (control->getIntAttribute (IDs::type) == 71)
140 expression->setAttribute (IDs::b, control->getDoubleAttribute (IDs::b));
141 expression->setAttribute (IDs::v, control->getIntAttribute (IDs::val) / 16383.0);
143 note->addChildElement (expression);
146 if (control->getIntAttribute (IDs::type) == 4101)
151 expression->setAttribute (IDs::b, control->getDoubleAttribute (IDs::b));
152 expression->setAttribute (IDs::v, range.convertFrom0to1 (control->getIntAttribute (IDs::val) / 16383.0f));
153 note->addChildElement (expression);
156 if (control->getIntAttribute (IDs::type) == 4103)
159 expression->setAttribute (IDs::b, control->getDoubleAttribute (IDs::b));
160 expression->setAttribute (IDs::v, control->getIntAttribute (IDs::val) / 16383.0f);
161 note->addChildElement (expression);
171 static void convertTrackMidiVersion (
juce::XmlElement& track,
double editTempo)
173 for (
auto clip : track.getChildWithTagNameIterator (
"CLIP"))
175 const double clipSpeed = clip->getDoubleAttribute (IDs::speed, 1.0);
176 const double timeToBeatFactor = (editTempo / 60.0) / clipSpeed;
177 convertSequenceMidiVersion (*clip, timeToBeatFactor);
187 auto editTempo = t->getDoubleAttribute (IDs::bpm);
190 convertTrackMidiVersion (*e, editTempo);
200 if (element->hasTagName (
"CLIP"))
202 if (
auto* sequence = element->getChildByName (
"MIDISEQUENCE"))
204 for (
auto note : sequence->getChildWithTagNameIterator (IDs::NOTE))
206 if (note->getFirstChildElement() !=
nullptr
207 && ! note->hasAttribute (IDs::bend))
209 if (
auto firstTimbre = note->getChildByName (IDs::TIMBRE))
210 note->setAttribute (IDs::timb, firstTimbre->getDoubleAttribute (
"v"));
212 if (
auto firstPressure = note->getChildByName (IDs::PRESSURE))
213 note->setAttribute (IDs::pres, firstPressure->getDoubleAttribute (
"v"));
215 if (
auto firstPitchbend = note->getChildByName (IDs::PITCHBEND))
216 note->setAttribute (IDs::bend, firstPitchbend->getDoubleAttribute (
"v"));
223 convertMpeVersion (*element);
244 for (
auto e : patterns->getChildIterator())
248 chan->setAttribute (IDs::pattern, chan->getAllSubText().trim());
249 chan->deleteAllChildElements();
250 chan->deleteAllTextElements();
254 for (
auto e : channels->getChildIterator())
256 renameAttribute (*e, IDs::noteNumber, IDs::note);
257 renameAttribute (*e, IDs::noteValue, IDs::velocity);
265 convertPluginsAndClips (*e);
271 e->
setAttribute (IDs::state, vstData->getAllSubText().trim());
286 updateOldStepClip (*e);
298 if (oldTempos.
size() > 0)
302 if (tempoSequence ==
nullptr)
305 for (
auto* e : oldTempos)
324 else if (
auto tempoSequence = xml.
getChildByName (IDs::TEMPOSEQUENCE))
326 bool foundOld =
false;
328 for (
auto e : tempoSequence->getChildWithTagNameIterator (IDs::TEMPO))
339 for (
auto e : oldTempos)
367 for (
auto e : viewStateXML->getChildWithTagNameIterator (IDs::MARKER))
373 if (numbers.
size() > 0)
377 if (markerTrack ==
nullptr)
382 markerTrack->setAttribute (IDs::trackType, (
int) 0 );
385 for (
int i = 0; i < numbers.
size(); ++i)
387 auto clip = markerTrack->createNewChildElement (
"CLIP");
388 clip->setAttribute (IDs::name,
"Marker");
389 clip->setAttribute (IDs::markerID, numbers[i]);
390 clip->setAttribute (IDs::type,
"absoluteMarker");
391 clip->setAttribute (IDs::start,
times[i]);
392 clip->setAttribute (IDs::length, 2.0);
407 moveAttribute (*viewStateXML, *videoXML,
"videoFile");
408 moveAttribute (*viewStateXML, *videoXML, IDs::videoOffset);
409 moveAttribute (*viewStateXML, *videoXML, IDs::videoMuted);
410 moveAttribute (*viewStateXML, *videoXML, IDs::videoSource);
420 if (transportXML ==
nullptr)
423 moveAttribute (*viewStateXML, *transportXML, IDs::markIn, IDs::loopPoint1);
424 moveAttribute (*viewStateXML, *transportXML, IDs::markOut, IDs::loopPoint2);
426 moveAttribute (*viewStateXML, *transportXML, IDs::loopPlayback, IDs::looping);
427 moveAttribute (*viewStateXML, *transportXML, IDs::automationRead);
428 moveAttribute (*viewStateXML, *transportXML, IDs::recordPunchInOut);
429 moveAttribute (*viewStateXML, *transportXML, IDs::endToEnd);
431 moveAttribute (*viewStateXML, *transportXML, IDs::midiTimecodeOffset);
432 moveAttribute (*viewStateXML, *transportXML, IDs::midiTimecodeEnabled);
433 moveAttribute (*viewStateXML, *transportXML, IDs::midiTimecodeIgnoringHours);
434 moveAttribute (*viewStateXML, *transportXML, IDs::midiTimecodeSourceDevice);
435 moveAttribute (*viewStateXML, *transportXML, IDs::midiMachineControlSourceDevice);
436 moveAttribute (*viewStateXML, *transportXML, IDs::midiMachineControlDestDevice);
443 for (
auto e : pitchSequence->getChildWithTagNameIterator (IDs::PITCH))
444 renameAttribute (*e, IDs::start, IDs::startBeat);
449 if (
auto firstMarkerTrack = xml.
getChildByName (IDs::MARKERTRACK))
455 if (firstMarkerTrack == markerTrack)
458 for (
auto clip : markerTrack->getChildWithTagNameIterator (
"CLIP"))
461 tracksToRemove.
add (markerTrack);
464 for (
auto markerTrack : tracksToRemove)
467 firstMarkerTrack->removeAttribute (IDs::trackType);
473 for (
auto e : tracks)
474 if (EditItemID::fromXML (*e,
"mediaId") == parentID)
487 addTracks (tracks, *e);
495 addTracks (tracks, xml);
497 for (
auto e : tracks)
504 if (tagsString.contains (
","))
509 for (
auto& tag : tags)
510 tag = tag.trimCharactersAtStart (
"_").trimCharactersAtEnd (
"_");
513 tags.removeEmptyStrings();
521 addTracks (tracks, xml);
523 for (
auto e : tracks)
525 auto parentID = EditItemID::fromXML (*e,
"parentId");
528 if (! parentID.isValid())
531 if (
auto p = getParentWithId (tracks, parentID))
534 p2->removeChildElement (e,
false);
538 p->addChildElement (e);
554 addNodeRecursively (plugins, *e, tagName);
560 addTracks (tracks, xml);
561 addNodeRecursively (plugins, xml, IDs::PLUGIN);
564 addNodeRecursively (plugins, xml,
"FILTER");
576 for (
auto t : tracks)
578 if (
auto lfos = t->getChildByName (IDs::LFOS))
580 lfosToDelete.
add (lfos);
582 auto modifiers = t->getChildByName (IDs::MODIFIERS);
584 if (modifiers ==
nullptr)
585 modifiers = t->createNewChildElement (IDs::MODIFIERS);
587 for (
auto lfo : lfos->getChildWithTagNameIterator (IDs::LFO))
590 modifiers->addChildElement (newLFO);
591 newLFO->setAttribute (IDs::syncType, 1);
592 newLFO->setAttribute (IDs::depth, lfo->getDoubleAttribute (IDs::intensity, 50.0) / 100.0);
593 newLFO->setAttribute (IDs::phase, lfo->getDoubleAttribute (IDs::phase) / 360.0);
595 if (lfo->getIntAttribute (IDs::sync, 1) == 0)
598 newLFO->setAttribute (IDs::rateType, 0);
599 newLFO->setAttribute (IDs::rate, lfo->getDoubleAttribute (IDs::frequency, 1.0));
604 newLFO->setAttribute (IDs::rateType, lfo->getIntAttribute (IDs::beat, 0) + 1.0);
605 newLFO->setAttribute (IDs::rate, 1.0);
619 for (
auto f : plugins)
621 auto modifierAssignments = f->getChildByName (IDs::MODIFIERASSIGNMENTS);
623 if (modifierAssignments ==
nullptr)
624 modifierAssignments = f->createNewChildElement (IDs::MODIFIERASSIGNMENTS);
626 for (
auto e : f->getChildWithTagNameIterator (IDs::AUTOMATIONSOURCE))
630 auto lfo = modifierAssignments->createNewChildElement (IDs::LFO);
633 lfo->setAttribute (IDs::value, 1.0);
635 automationSourcesToDelete.
add (e);
640 for (
auto lfos : lfosToDelete)
642 p->removeChildElement (lfos,
true);
644 for (
auto automationSource : automationSourcesToDelete)
646 p->removeChildElement (automationSource,
true);
651 renameLegacyIDs (xml);
654 EditItemID::remapIDs (xml, [&] {
return EditItemID::fromRawID (nextID++); });
656 recurseDoingLegacyConversions (xml);
665 renameAttribute (xml,
"mediaId", IDs::projectID);
666 moveXMLAttributeToStart (xml, IDs::projectID);
667 moveXMLAttributeToStart (xml, IDs::appVersion);
669 convertLegacyIDs (xml);
672 convertLegacyTimecodes (xml);
673 convertLegacyInputTargets (xml);
677 convertLegacyIDs (xml);
690 renameLegacyIDs (*e);
694 renameAttribute (xml,
"mediaId", IDs::source);
704 renameAttribute (xml,
"mediaId", IDs::id);
705 renameAttribute (xml,
"markerId", IDs::markerID);
706 renameAttribute (xml,
"groupId", IDs::groupID);
707 renameAttribute (xml,
"linkId", IDs::linkID);
708 renameAttribute (xml,
"currentAutoParamFilter", IDs::currentAutoParamPluginID);
718 tidyIDListDelimiters (xml, IDs::ghostTracks);
720 else if (xml.
hasTagName (IDs::CONTROLLERMAPPINGS))
722 renameAttribute (xml,
"filterid", IDs::pluginID);
726 renameAttribute (xml,
"videoFileId", IDs::videoSource);
727 renameAttribute (xml,
"filterAreaWidth", IDs::pluginAreaWidth);
728 renameAttribute (xml,
"filtersVisible", IDs::pluginsVisible);
729 tidyIDListDelimiters (xml, IDs::hiddenClips);
730 tidyIDListDelimiters (xml, IDs::lockedClips);
740 if (name.endsWith (
" A") || name.endsWith (
" M"))
742 xml.
setAttribute (IDs::sourceTrack, name.upToLastOccurrenceOf (
" ",
false,
false));
743 xml.
setAttribute (IDs::type, name.endsWith (
" M") ?
"MIDI" :
"audio");
747 else if (xml.
hasTagName (IDs::INPUTDEVICEDESTINATION))
749 renameAttribute (xml,
"targetTrack", IDs::targetID);
753 renameAttribute (xml,
"renderFilter", IDs::renderPlugins);
760 moveXMLAttributeToStart (xml, IDs::id);
803 if (timeFormat ==
"0" || timeFormat.contains (
"milli"))
return setNewTimecode (xml, TimecodeType::millisecs);
804 if (timeFormat ==
"1" || timeFormat.contains (
"beat"))
return setNewTimecode (xml, TimecodeType::barsBeats);
806 if (timeFormat ==
"2")
return setNewTimecode (xml, TimecodeType::fps24);
807 if (timeFormat ==
"3")
return setNewTimecode (xml, TimecodeType::fps25);
808 if (timeFormat ==
"4")
return setNewTimecode (xml, TimecodeType::fps30);
810 if (fps != 0 && timeFormat ==
"frames")
812 if (fps == 24)
return setNewTimecode (xml, TimecodeType::fps24);
813 if (fps == 25)
return setNewTimecode (xml, TimecodeType::fps25);
814 if (fps == 30)
return setNewTimecode (xml, TimecodeType::fps30);
827 renameAttribute (xml,
"noteOffVelocity", IDs::lift);
832 renameAttribute (xml,
"initialTimbre", IDs::timb);
834 if (xml.
getDoubleAttribute (
"initialPressure") == MidiList::defaultInitialPressureValue)
837 renameAttribute (xml,
"initialPressure", IDs::pres);
839 if (xml.
getDoubleAttribute (
"initialPitchbend") == MidiList::defaultInitialPitchBendValue)
842 renameAttribute (xml,
"initialPitchbend", IDs::bend);
849 convertLegacyInputTargets (*e);
851 if (xml.
hasTagName (IDs::INPUTDEVICEDESTINATION))
852 renameAttribute (xml,
"targetTrack", IDs::targetID);
858 recurseDoingLegacyConversions (*e);
860 convertLegacyFilterTagsToPlugin (xml);
861 convertLegacyRackConnectionIDs (xml);
862 convertLegacyClipFormat (xml);
863 convertLegacyMidiSequences (xml);