File: importmidi_operations.h

package info (click to toggle)
musescore3 3.2.3%2Bdfsg2-19
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 218,192 kB
  • sloc: cpp: 291,369; xml: 200,226; sh: 3,779; ansic: 1,447; python: 393; makefile: 249; perl: 82; pascal: 79
file content (295 lines) | stat: -rw-r--r-- 9,863 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#ifndef IMPORTMIDI_OPERATIONS_H
#define IMPORTMIDI_OPERATIONS_H

#include "importmidi_inner.h"
#include "importmidi_operation.h"
#include "midi/midifile.h"


namespace Ms {

class ReducedFraction;
class InstrumentTemplate;

namespace MidiCharset {
      QString defaultCharset();
}
namespace Quantize {
      MidiOperations::QuantValue defaultQuantValueFromPreferences();
}

namespace MidiOperations {

// operation types are in importmidi_operation.h

// to add an operation one need to add code also to:
//   - importmidi_operation.h,
//   - importmidi_opmodel.cpp (2 places),
//   - importmidi_trmodel.cpp (2 places),
// and - other importmidi files where algorithm requires it

template<typename T>
class TrackOp
      {
   public:
      explicit TrackOp(T defaultValue)
            : _operation{{-1, defaultValue}}, _canRedefineDefaultLater(true)
            {}

      const T& value(int trackIndex) const
            {
            const auto it = _operation.find(trackIndex);
            if (it == _operation.end())
                  return _operation.find(-1)->second;
            return it->second;
            }

      void setValue(int trackIndex, T value)
            {
            Q_ASSERT_X(trackIndex >= 0, "TrackOperation", "Invalid track index");

            if (value != this->value(trackIndex))
                  _operation[trackIndex] = value;
            }

      const T& defaultValue() const
            {
            return _operation.find(-1)->second;
            }

      bool canRedefineDefaultLater() const { return _canRedefineDefaultLater; }

      void setDefaultValue(T value, bool canRedefineDefaultLater = true)
            {
            Q_ASSERT_X(_canRedefineDefaultLater, "TrackOp::setDefaultValue",
                       "Cannot set default value");

            if (!_canRedefineDefaultLater)
                  return;
            _operation[-1] = value;
            _canRedefineDefaultLater = canRedefineDefaultLater;
            }

      void clear()
            {
            T defaultVal = defaultValue();
            _operation.clear();
            _operation[-1] = defaultVal;
            }
   private:
                  // <track index, operation value>
                  // if track index == -1 then it's default value (for all tracks)
      std::map<int, T> _operation;
      bool _canRedefineDefaultLater;
      };

template<typename T>
class Op
      {
   public:

      explicit Op(T defaultValue)
            : _value(defaultValue), _valueWasSet(false),
              _defaultValue{defaultValue}, _canRedefineDefaultLater(true)
            {}

      T value() const
            {
            if (!_valueWasSet)
                  return _defaultValue;
            return _value;
            }

      void setValue(T value)
            {
            if (value != this->value()) {
                  _value = value;
                  _valueWasSet = true;
                  }
            }

      T defaultValue() const
            {
            return _defaultValue;
            }

      bool canRedefineDefaultLater() const { return _canRedefineDefaultLater; }

      void setDefaultValue(T value, bool canRedefineDefaultLater = true)
            {
            Q_ASSERT_X(_canRedefineDefaultLater, "Op::setDefaultValue",
                       "Cannot set default value");

            if (!_canRedefineDefaultLater)
                  return;
            _defaultValue = value;
            _canRedefineDefaultLater = canRedefineDefaultLater;
            }
   private:
      T _value;
      bool _valueWasSet;
      T _defaultValue;
      bool _canRedefineDefaultLater;
      };

// values that can be changed

struct Opers
      {
                  // data that cannot be changed by the user
      TrackOp<int> channel = TrackOp<int>(int());
      TrackOp<std::string> staffName = TrackOp<std::string>(std::string());       // will be converted to unicode later
      TrackOp<QString> midiInstrName = TrackOp<QString>(QString());
      TrackOp<std::vector<const InstrumentTemplate *> > msInstrList
                        = TrackOp<std::vector<const InstrumentTemplate *> >(
                                              std::vector<const InstrumentTemplate *>());
      TrackOp<bool> isDrumTrack = TrackOp<bool>(false);

                  // operations for all tracks
      Op<bool> isHumanPerformance = Op<bool>(false);
      Op<bool> searchPickupMeasure = Op<bool>(true);
      Op<bool> measureCount2xLess = Op<bool>(false);
      Op<bool> showTempoText = Op<bool>(true);
      Op<bool> showChordNames = Op<bool>(true);
      Op<TimeSigNumerator> timeSigNumerator = Op<TimeSigNumerator>(TimeSigNumerator::_4);
      Op<TimeSigDenominator> timeSigDenominator = Op<TimeSigDenominator>(TimeSigDenominator::_4);

                  // operations for individual tracks
      TrackOp<int> trackIndexAfterReorder = TrackOp<int>(0);
      TrackOp<bool> doImport = TrackOp<bool>(true);
      TrackOp<QuantValue> quantValue = TrackOp<QuantValue>(Quantize::defaultQuantValueFromPreferences());
      TrackOp<bool> searchTuplets = TrackOp<bool>(true);
      TrackOp<bool> search2plets = TrackOp<bool>(false);
      TrackOp<bool> search3plets = TrackOp<bool>(true);
      TrackOp<bool> search4plets = TrackOp<bool>(true);
      TrackOp<bool> search5plets = TrackOp<bool>(true);
      TrackOp<bool> search7plets = TrackOp<bool>(true);
      TrackOp<bool> search9plets = TrackOp<bool>(true);
      TrackOp<bool> useDots = TrackOp<bool>(true);
      TrackOp<bool> simplifyDurations = TrackOp<bool>(true);   // for drum tracks - remove rests and ties
      TrackOp<bool> showStaccato = TrackOp<bool>(true);
      TrackOp<bool> doStaffSplit = TrackOp<bool>(false);       // for drum tracks - split by voices
      TrackOp<VoiceCount> maxVoiceCount = TrackOp<VoiceCount>(VoiceCount::V_4);
      TrackOp<bool> changeClef = TrackOp<bool>(true);
      TrackOp<Swing> swing = TrackOp<Swing>(Swing::NONE);
      TrackOp<bool> removeDrumRests = TrackOp<bool>(true);
      TrackOp<int> lyricTrackIndex = TrackOp<int>(-1);         // empty lyric
      TrackOp<int> msInstrIndex = TrackOp<int>(-1);            // for empty instrument list
      };

struct HumanBeatData
      {
      std::set<ReducedFraction> beatSet;
                // to adapt human beats to a different time sig, if necessary
      int addedFirstBeats = 0;
      int addedLastBeats = 0;
      ReducedFraction firstChordTick;
      ReducedFraction lastChordTick;
      ReducedFraction timeSig;
      bool measureCount2xLess = false;
      };

struct FileData
      {
      MidiFile midiFile;
      QList<MTrack> tracks;
      int processingsOfOpenedFile = 0;
      bool hasTempoText = false;
      QByteArray HHeaderData;
      QByteArray VHeaderData;
      int trackCount = 0;
      Opers trackOpers;
      QString charset = MidiCharset::defaultCharset();
                  // after the user apply MIDI import operations
                  // this value should be set to false
                  // tracks of <tick, lyric fragment> from karaoke files
                  // QList of lyric tracks - there can be multiple lyric tracks,
                  // lyric track count != MIDI track count in general
      QList<std::multimap<ReducedFraction, std::string>> lyricTracks;
      std::multimap<ReducedFraction, QString> chordNames;
      HumanBeatData humanBeatData;
      };

class Data
      {
   public:
      FileData* data();
      const FileData* data() const;

      void addNewMidiFile(const QString &fileName);
      int currentTrack() const;
      void setMidiFileData(const QString &fileName, const MidiFile &midiFile);
      void excludeMidiFile(const QString &fileName);
      bool hasMidiFile(const QString &fileName);
      const MidiFile* midiFile(const QString &fileName);
      QStringList allMidiFiles() const;
      void setOperationsFile(const QString &fileName);

   private:
      friend class CurrentTrackSetter;
      friend class CurrentMidiFileSetter;

      QString _currentMidiFile;
      QString _midiOperationsFile;
      int _currentTrack = -1;

      std::map<QString, FileData> _data;    // <file name, tracks data>
      };

// scoped setter of current track
class CurrentTrackSetter
      {
   public:
      CurrentTrackSetter(Data &opers, int track)
            : _opers(opers)
            {
            _oldValue = _opers._currentTrack;
            _opers._currentTrack = track;
            }

      ~CurrentTrackSetter()
            {
            _opers._currentTrack = _oldValue;
            }
   private:
      Data &_opers;
      int _oldValue;
                  // disallow heap allocation - for stack-only usage
      void* operator new(size_t);               // standard new
      void* operator new(size_t, void*);        // placement new
      void* operator new[](size_t);             // array new
      void* operator new[](size_t, void*);      // placement array new
      };

// scoped setter of current MIDI file
class CurrentMidiFileSetter
      {
   public:
      CurrentMidiFileSetter(Data &opers, const QString &fileName)
            : _opers(opers)
            {
            _oldValue = _opers._currentMidiFile;
            _opers._currentMidiFile = fileName;
            }

      ~CurrentMidiFileSetter()
            {
            _opers._currentMidiFile = _oldValue;
            }
   private:
      Data &_opers;
      QString _oldValue;
                  // disallow heap allocation - for stack-only usage
      void* operator new(size_t);               // standard new
      void* operator new(size_t, void*);        // placement new
      void* operator new[](size_t);             // array new
      void* operator new[](size_t, void*);      // placement array new
      };

} // namespace MidiOperations

extern MidiOperations::Data midiImportOperations;
} // namespace Ms


#endif // IMPORTMIDI_OPERATIONS_H