1 package net.kreatious.pianoleopard.midi.track;
2
3 import static java.util.stream.Collectors.toList;
4
5 import java.io.File;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.Optional;
10 import java.util.concurrent.CopyOnWriteArrayList;
11 import java.util.stream.Stream;
12
13 import javax.sound.midi.InvalidMidiDataException;
14 import javax.sound.midi.Sequence;
15 import javax.sound.midi.Track;
16
17 import net.kreatious.pianoleopard.midi.event.TempoCache;
18
19
20
21
22
23
24 public class ParsedSequence {
25 private final List<ParsedTrack> inactiveTracks = new CopyOnWriteArrayList<>();
26 private final List<ParsedTrack> activeTracks = new CopyOnWriteArrayList<>();
27 private final List<ParsedTrack> tracks;
28 private final Sequence sequence;
29
30
31
32
33
34 private Optional<File> file = null;
35
36 private ParsedSequence(Sequence sequence, Track[] tracks, TempoCache cache) {
37 this.sequence = sequence;
38 this.tracks = Stream.of(tracks).map(track -> new ImmutableParsedTrack(track, cache)).collect(toList());
39 activeTracks.addAll(this.tracks);
40 }
41
42
43
44
45
46
47
48
49
50
51 public Optional<File> getFile() {
52 return Optional.ofNullable(file).orElse(Optional.empty());
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66 public void setFile(Optional<File> file) {
67 if (this.file != null) {
68 throw new IllegalStateException("Cannot set the file to " + file + "; already set to " + this.file);
69 }
70 this.file = file;
71 }
72
73
74
75
76
77
78 public List<ParsedTrack> getTracks() {
79 return Collections.unmodifiableList(tracks);
80 }
81
82
83
84
85
86
87
88
89
90 public Collection<ParsedTrack> getActiveTracks() {
91 return Collections.unmodifiableCollection(activeTracks);
92 }
93
94
95
96
97
98
99
100
101
102 public Collection<ParsedTrack> getInactiveTracks() {
103 return Collections.unmodifiableCollection(inactiveTracks);
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public void setTrackActive(ParsedTrack track, boolean active) {
119 if (!tracks.contains(track)) {
120 throw new IllegalArgumentException("Specified track is not contained by this container.");
121 }
122
123 if (active && inactiveTracks.contains(track)) {
124 inactiveTracks.remove(track);
125 activeTracks.add(track);
126 } else if (!active && activeTracks.contains(track)) {
127 activeTracks.remove(track);
128 inactiveTracks.add(track);
129 }
130 }
131
132
133
134
135
136
137 public Sequence getSequence() {
138 return sequence;
139 }
140
141
142
143
144
145
146 public static ParsedSequence createEmpty() {
147 try {
148 final Sequence sequence = new Sequence(Sequence.SMPTE_25, 1);
149 return new ParsedSequence(sequence, new Track[0], new TempoCache(sequence));
150 } catch (final InvalidMidiDataException e) {
151 throw new IllegalStateException(e);
152 }
153 }
154
155
156
157
158
159
160
161
162 public static ParsedSequence parseByTracks(Sequence sequence) {
163 return new ParsedSequence(sequence, sequence.getTracks(), new TempoCache(sequence));
164 }
165 }