Skip to content

Commit e03e0c7

Browse files
committed
* New: Support enable state (mute) of clips.
* New: Moved markers from Lanes to Arrangement to be compatible with Studio One. * Fixed: Continue conversion when end notes without start notes are found.
1 parent b6ddcf9 commit e03e0c7

6 files changed

Lines changed: 42 additions & 18 deletions

File tree

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ Range markers are not supported.
162162

163163
## Changes
164164

165+
### 1.2.10
166+
167+
* New: Support enable state (mute) of clips.
168+
* New: Moved markers from Lanes to Arrangement to be compatible with Studio One.
169+
* Fixed: Continue conversion when end notes without start notes are found.
170+
171+
165172
### 1.2.9
166173

167174
* New: Support for FLAC files.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>de.mossgrabers</groupId>
77
<artifactId>projectconverter</artifactId>
8-
<version>1.2.9</version>
8+
<version>1.2.10</version>
99
<name>ProjectConverter</name>
1010
<description>Convert from/to a specific DAW project format to/from generic
1111
dawproject</description>

src/main/java/de/mossgrabers/projectconverter/format/reaper/ReaperCreator.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -771,18 +771,18 @@ private void convertTrack (final IMediaFiles mediaFiles, final List<TrackInfo> f
771771
* @param parentClip Some aggregated info about the parent clip(s)
772772
* @param parameters The parameters
773773
*/
774-
private void convertItems (final Chunk trackChunk, final Track track, final Clips clips, final ParentClip parentClip, final Parameters parameters)
774+
private void convertClips (final Chunk trackChunk, final Track track, final Clips clips, final ParentClip parentClip, final Parameters parameters)
775775
{
776776
if (clips.clips == null)
777777
return;
778778

779779
final boolean clipsIsBeats = TimeUtils.updateIsBeats (clips, parentClip.sourceIsBeats);
780780
for (final Clip clip: clips.clips)
781-
this.convertItem (trackChunk, track, clip, parentClip, parameters, clipsIsBeats);
781+
this.convertClip (trackChunk, track, clip, parentClip, parameters, clipsIsBeats);
782782
}
783783

784784

785-
private void convertItem (final Chunk trackChunk, final Track track, final Clip clip, final ParentClip parentClip, final Parameters parameters, final boolean clipsIsBeats)
785+
private void convertClip (final Chunk trackChunk, final Track track, final Clip clip, final ParentClip parentClip, final Parameters parameters, final boolean clipsIsBeats)
786786
{
787787
final Double tempo = parameters.tempo;
788788
final boolean destinationIsBeats = parameters.destinationIsBeats;
@@ -807,6 +807,7 @@ private void convertItem (final Chunk trackChunk, final Track track, final Clip
807807
{
808808
final ParentClip innerParentClip = new ParentClip ();
809809
innerParentClip.comment = clip.comment;
810+
innerParentClip.mute = clip.enable != null && !clip.enable.booleanValue ();
810811

811812
// Harmonize all time based values to the destination
812813
innerParentClip.sourceIsBeats = clipContentIsBeats;
@@ -822,7 +823,7 @@ private void convertItem (final Chunk trackChunk, final Track track, final Clip
822823
innerParentClip.loopStart = clip.loopStart == null ? 0 : handleTime (clip.loopStart.doubleValue (), clipContentIsBeats, destinationIsBeats, tempo);
823824
innerParentClip.loopEnd = clip.loopEnd == null ? -1 : handleTime (clip.loopEnd.doubleValue (), clipContentIsBeats, destinationIsBeats, tempo);
824825

825-
this.convertItems (trackChunk, track, groupedClips, innerParentClip, parameters);
826+
this.convertClips (trackChunk, track, groupedClips, innerParentClip, parameters);
826827
return;
827828
}
828829

@@ -855,7 +856,7 @@ private void convertItem (final Chunk trackChunk, final Track track, final Clip
855856

856857
final Double fadeIn = handleTime (clip.fadeInTime, destinationIsBeats, parameters);
857858
final Double fadeOut = handleTime (clip.fadeOutTime, destinationIsBeats, parameters);
858-
final Chunk itemChunk = createClipChunk (trackChunk, clip.name, start, clipDuration, offset, fadeIn, fadeOut);
859+
final Chunk itemChunk = createClipChunk (trackChunk, clip.name, start, clipDuration, offset, fadeIn, fadeOut, parentClip.mute || (clip.enable != null && !clip.enable.booleanValue ()));
859860

860861
if (parentClip.comment != null && !parentClip.comment.isBlank ())
861862
createNotesChunk (itemChunk, parentClip.comment, ReaperTags.PROJECT_NOTES);
@@ -910,16 +911,19 @@ private void convertLoopedAudio (final Chunk trackChunk, final Clip clip, final
910911

911912
final Double fadeIn = handleTime (clip.fadeInTime, isBeats, parameters);
912913
final Double fadeOut = handleTime (clip.fadeOutTime, isBeats, parameters);
913-
itemChunk = createClipChunk (trackChunk, clip.name, start, duration, clipOffset, fadeIn, fadeOut);
914+
itemChunk = createClipChunk (trackChunk, clip.name, start, duration, clipOffset, fadeIn, fadeOut, parentClip.mute || (clip.enable != null && !clip.enable.booleanValue ()));
914915
}
915916
}
916917

917918

918-
private static Chunk createClipChunk (final Chunk trackChunk, final String clipName, final double start, final double duration, final double offset, final Double fadeIn, final Double fadeOut)
919+
private static Chunk createClipChunk (final Chunk trackChunk, final String clipName, final double start, final double duration, final double offset, final Double fadeIn, final Double fadeOut, final boolean mute)
919920
{
920921
final Chunk itemChunk = addChunk (trackChunk, ReaperTags.CHUNK_ITEM);
921922
if (clipName != null)
922923
addNode (itemChunk, ReaperTags.ITEM_NAME, clipName);
924+
if (mute)
925+
addNode (itemChunk, ReaperTags.ITEM_MUTE, "1");
926+
923927
addNode (itemChunk, ReaperTags.ITEM_POSITION, Double.toString (start));
924928
addNode (itemChunk, ReaperTags.ITEM_LENGTH, Double.toString (duration));
925929
addNode (itemChunk, ReaperTags.ITEM_SAMPLE_OFFSET, Double.toString (offset));
@@ -1124,6 +1128,9 @@ private void convertArrangementLanes (final Chunk rootChunk, final Project proje
11241128
if (project.arrangement == null || project.arrangement.lanes == null)
11251129
return;
11261130

1131+
if (project.arrangement.markers != null)
1132+
this.convertMarkers (rootChunk, parameters, project.arrangement.markers, arrangementIsBeats);
1133+
11271134
for (final Timeline timeline: project.arrangement.lanes.lanes)
11281135
if (timeline instanceof final Markers markers && markers.markers != null)
11291136
this.convertMarkers (rootChunk, parameters, markers, arrangementIsBeats);
@@ -1178,7 +1185,7 @@ private void convertScenes (final Chunk rootChunk, final Project project, final
11781185
final double duration = TimeUtils.getDuration (clip);
11791186
for (double pos = 0; pos < maxDuration; pos += duration)
11801187
{
1181-
this.convertItem (trackChunk, track, clip, parentClip, parameters, isBeats);
1188+
this.convertClip (trackChunk, track, clip, parentClip, parameters, isBeats);
11821189
clip.time += duration;
11831190
}
11841191
}
@@ -1240,7 +1247,7 @@ else if (trackTimeline instanceof final Clips clips)
12401247
{
12411248
final ParentClip parentClip = new ParentClip ();
12421249
parentClip.valuesIsBeats = timelineIsBeats;
1243-
this.convertItems (trackChunk, track, clips, parentClip, parameters);
1250+
this.convertClips (trackChunk, track, clips, parentClip, parameters);
12441251
}
12451252
else if (trackTimeline instanceof final Warps warps)
12461253
this.convertWarps (rootOrItemChunk, parameters, warps, arrangementIsBeats);
@@ -1729,6 +1736,7 @@ private static class ParentClip
17291736
boolean valuesIsBeats = true;
17301737

17311738
String comment;
1739+
boolean mute;
17321740
// The start of the loop
17331741
double loopEnd;
17341742
// The end of the loop

src/main/java/de/mossgrabers/projectconverter/format/reaper/ReaperDetector.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ private static void convertMarkers (final DawProjectContainer dawProject, final
400400
}
401401

402402
if (!cueMarkers.markers.isEmpty ())
403-
dawProject.getProject ().arrangement.lanes.lanes.add (cueMarkers);
403+
dawProject.getProject ().arrangement.markers = cueMarkers;
404404
}
405405

406406

@@ -639,7 +639,7 @@ private Track convertTrack (final DawProjectContainer dawProject, final Map<Stri
639639
// Convert all FX devices
640640
channel.devices = this.convertDevices (mediaFilesMap, track, trackChunk, ReaperTags.CHUNK_FXCHAIN, folderStructure);
641641

642-
final Set<ContentType> trackTypes = this.convertItems (dawProject, mediaFilesMap, trackLanes, trackChunk, sourcePath, beatsAndTime);
642+
final Set<ContentType> trackTypes = this.convertClips (dawProject, mediaFilesMap, trackLanes, trackChunk, sourcePath, beatsAndTime);
643643

644644
if (auxReceive.isEmpty ())
645645
{
@@ -1043,7 +1043,7 @@ private Device convertDevice (final Map<String, File> mediaFilesMap, final Chunk
10431043
* @return The type of converted clips
10441044
* @throws ParseException Could not parse the track info
10451045
*/
1046-
private Set<ContentType> convertItems (final DawProjectContainer dawProject, final Map<String, File> mediaFilesMap, final Lanes trackLanes, final Chunk trackChunk, final File sourcePath, final BeatsAndTime beatsAndTime) throws ParseException
1046+
private Set<ContentType> convertClips (final DawProjectContainer dawProject, final Map<String, File> mediaFilesMap, final Lanes trackLanes, final Chunk trackChunk, final File sourcePath, final BeatsAndTime beatsAndTime) throws ParseException
10471047
{
10481048
final Set<ContentType> contentTypes = new HashSet<> ();
10491049

@@ -1059,7 +1059,7 @@ private Set<ContentType> convertItems (final DawProjectContainer dawProject, fin
10591059

10601060
if (node instanceof final Chunk itemChunk)
10611061
{
1062-
final Clip clip = this.handleClip (dawProject, mediaFilesMap, itemChunk, sourcePath, beatsAndTime, contentTypes);
1062+
final Clip clip = this.convertClip (dawProject, mediaFilesMap, itemChunk, sourcePath, beatsAndTime, contentTypes);
10631063
if (clip != null)
10641064
clips.clips.add (clip);
10651065
}
@@ -1091,7 +1091,7 @@ private static Lanes createTrackLanes (final Project project, final Track track,
10911091
* @return The clip
10921092
* @throws ParseException Could not parse a clip
10931093
*/
1094-
private Clip handleClip (final DawProjectContainer dawProject, final Map<String, File> mediaFilesMap, final Chunk itemChunk, final File sourcePath, final BeatsAndTime beatsAndTime, final Set<ContentType> contentTypes) throws ParseException
1094+
private Clip convertClip (final DawProjectContainer dawProject, final Map<String, File> mediaFilesMap, final Chunk itemChunk, final File sourcePath, final BeatsAndTime beatsAndTime, final Set<ContentType> contentTypes) throws ParseException
10951095
{
10961096
final Clip clip = new Clip ();
10971097

@@ -1103,6 +1103,10 @@ private Clip handleClip (final DawProjectContainer dawProject, final Map<String,
11031103
double clipPosition = getDoubleParam (itemChunk.getChildNode (ReaperTags.ITEM_POSITION), 0);
11041104
double clipDuration = getDoubleParam (itemChunk.getChildNode (ReaperTags.ITEM_LENGTH), 1);
11051105

1106+
final boolean clipMute = getDoubleParam (itemChunk.getChildNode (ReaperTags.ITEM_MUTE), 0) > 0;
1107+
if (clipMute)
1108+
clip.enable = Boolean.FALSE;
1109+
11061110
clip.name = getParam (itemChunk.getChildNode (ReaperTags.ITEM_NAME), null);
11071111
clip.time = handleTime (beatsAndTime, clipPosition, false);
11081112
clip.contentTimeUnit = beatsAndTime.destinationIsBeats ? TimeUnit.BEATS : TimeUnit.SECONDS;
@@ -1201,7 +1205,7 @@ private Clip handleClip (final DawProjectContainer dawProject, final Map<String,
12011205
* @return The end of the MIDI events
12021206
* @throws ParseException Could not parse the notes
12031207
*/
1204-
private static double convertMIDI (final DawProjectContainer dawProject, final Chunk sourceChunk, final Lanes lanes, final BeatsAndTime beatsAndTime) throws ParseException
1208+
private double convertMIDI (final DawProjectContainer dawProject, final Chunk sourceChunk, final Lanes lanes, final BeatsAndTime beatsAndTime) throws ParseException
12051209
{
12061210
final Notes notes = new Notes ();
12071211
lanes.lanes.add (notes);
@@ -1237,7 +1241,10 @@ private static double convertMIDI (final DawProjectContainer dawProject, final C
12371241
case 0x80:
12381242
final ReaperMidiEvent noteStart = findNoteStart (noteStarts, midiEvent);
12391243
if (noteStart == null)
1240-
throw new ParseException ("Malformed MIDI events in MIDI source section. End note without start note.", 0);
1244+
{
1245+
this.notifier.logError ("IDS_NOTIFY_ERR_NO_END_NOTE", Integer.toString (midiEvent.getData1 ()), Integer.toString (midiEvent.getData2 ()));
1246+
continue;
1247+
}
12411248
noteStarts.remove (noteStart);
12421249

12431250
final Note note = new Note ();

src/main/java/de/mossgrabers/projectconverter/format/reaper/ReaperTags.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class ReaperTags
5555

5656
protected static final String CHUNK_ITEM = "ITEM";
5757
protected static final String ITEM_NAME = "NAME";
58+
protected static final String ITEM_MUTE = "MUTE";
5859
protected static final String ITEM_NOTES = "NOTES";
5960
protected static final String ITEM_POSITION = "POSITION";
6061
protected static final String ITEM_LENGTH = "LENGTH";

src/main/resources/Strings.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
TITLE=ProjectConverter 1.2.9
1+
TITLE=ProjectConverter 1.2.10
22

33
##################################################################################
44
#
@@ -50,6 +50,7 @@ IDS_NOTIFY_UNSUPPORTED_ENVELOPE=Automation envelope not supported for: %1\n
5050
IDS_NOTIFY_UNKNOWN_AUDIO_FORMAT=Could not retrieve audio file format: %1\n
5151
IDS_NOTIFY_PROCESSING=Processing
5252
IDS_NOTIFY_FINISHED=Finished
53+
IDS_NOTIFY_ERR_NO_END_NOTE=End note without start note: %1 %2\n
5354

5455
###################################################################################
5556
# UI

0 commit comments

Comments
 (0)