1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //    operations.h
5 //  (C) Copyright 2014, 2016 Tim E. Real (terminator356 on users dot sourceforge dot net)
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; version 2 of
10 //  the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 //=========================================================
22 
23 #ifndef __OPERATIONS_H__
24 #define __OPERATIONS_H__
25 
26 #include <list>
27 #include <map>
28 #include <set>
29 #include <stdint.h>
30 
31 #include "type_defs.h"
32 #include "muse_time.h"
33 #include "event.h"
34 #include "midictrl.h"
35 #include "ctrl.h"
36 #include "time_stretch.h"
37 #include "part.h"
38 #include "track.h"
39 #include "route.h"
40 #include "mididev.h"
41 #include "marker/marker.h"
42 #include "instruments/minstrument.h"
43 #include "wave.h"
44 #include "pos.h"
45 
46 namespace MusECore {
47 
48 // Forward declarations:
49 class TempoList;
50 class SigList;
51 class KeyList;
52 class MidiPort;
53 class MetroAccentsMap;
54 class AudioConverterSettingsGroup;
55 class AudioConverterPluginI;
56 
57 typedef std::list < iMidiCtrlValList > MidiCtrlValListIterators_t;
58 typedef MidiCtrlValListIterators_t::iterator iMidiCtrlValListIterators_t;
59 typedef MidiCtrlValListIterators_t::const_iterator ciMidiCtrlValListIterators_t;
60 class MidiCtrlValListIterators : public MidiCtrlValListIterators_t
61 {
62    public:
63      iterator findList(const MidiCtrlValList* valList);
64      const_iterator findList(const MidiCtrlValList* valList) const;
65 };
66 
67 typedef std::map < int /*port*/, MidiCtrlValListIterators, std::less<int> > MidiCtrlValLists2bErased_t;
68 typedef MidiCtrlValLists2bErased_t::iterator iMidiCtrlValLists2bErased_t;
69 typedef MidiCtrlValLists2bErased_t::const_iterator ciMidiCtrlValLists2bErased_t;
70 typedef std::pair<iMidiCtrlValLists2bErased_t, bool> MidiCtrlValLists2bErasedInsertResult_t;
71 typedef std::pair<int, MidiCtrlValListIterators> MidiCtrlValLists2bErasedInsertPair_t;
72 typedef std::pair<iMidiCtrlValLists2bErased_t, iMidiCtrlValLists2bErased_t> MidiCtrlValLists2bErasedRangePair_t;
73 
74 class MidiCtrlValLists2bErased : public MidiCtrlValLists2bErased_t
75 {
76    public:
77      void add(int port, const iMidiCtrlValList& item);
78      iterator findList(int port, const MidiCtrlValList* valList);
79      const_iterator findList(int port, const MidiCtrlValList* valList) const;
80 };
81 
82 
83 typedef std::set < MidiCtrlValList* > MidiCtrlValLists2bDeleted_t;
84 typedef MidiCtrlValLists2bDeleted_t::iterator iMidiCtrlValLists2bDeleted_t;
85 typedef MidiCtrlValLists2bDeleted_t::const_iterator ciMidiCtrlValLists2bDeleted_t;
86 class MidiCtrlValLists2bDeleted : public MidiCtrlValLists2bDeleted_t
87 {
88 
89 };
90 
91 
92 typedef std::map < int /*port*/, MidiCtrlValListList*, std::less<int> > MidiCtrlValLists2bAdded_t;
93 typedef MidiCtrlValLists2bAdded_t::iterator iMidiCtrlValLists2bAdded_t;
94 typedef MidiCtrlValLists2bAdded_t::const_iterator ciMidiCtrlValLists2bAdded_t;
95 typedef std::pair<iMidiCtrlValLists2bAdded_t, bool> MidiCtrlValLists2bAddedInsertResult_t;
96 typedef std::pair<int, MidiCtrlValListList*> MidiCtrlValLists2bAddedInsertPair_t;
97 typedef std::pair<iMidiCtrlValLists2bAdded_t, iMidiCtrlValLists2bAdded_t> MidiCtrlValLists2bAddedRangePair_t;
98 
99 class MidiCtrlValLists2bAdded : public MidiCtrlValLists2bAdded_t
100 {
101 //   public:
102 //     void add(int port, const MidiCtrlValListList* item);
103 //     void remove(int port, const MidiCtrlValListList* item);
104 };
105 
106 
107 struct MidiCtrlValRemapOperation
108 {
109   // Iterators to be erased in realtime stage.
110   MidiCtrlValLists2bErased _midiCtrlValLists2bErased;
111   // New items to be added in realtime stage.
112   MidiCtrlValLists2bAdded _midiCtrlValLists2bAdded;
113   // Orphaned pointers after the iterators have been erased, deleted in post non-realtime stage.
114   // Automatically filled by constructor.
115   MidiCtrlValLists2bDeleted_t _midiCtrlValLists2bDeleted;
116 };
117 
118 struct DrumMapTrackOperation
119 {
120   // Whether this is a setting operation or a reset to defaults.
121   bool _isReset;
122   bool _isInstrumentMod;
123   bool _doWholeMap;
124   bool _includeDefault;
125   WorkingDrumMapList _workingItemList;
126   // List of tracks to apply to.
127   MidiTrackList _tracks;
128 };
129 
130 struct DrumMapTrackPatchOperation
131 {
132   // Whether to clear the list of overrides.
133   bool _clear;
134   // Whether this is a setting operation or a reset to defaults.
135   bool _isReset;
136   bool _isInstrumentMod;
137   WorkingDrumMapPatchList _workingItemPatchList;
138   // List of tracks to apply to.
139   MidiTrackList _tracks;
140 };
141 
142 struct DrumMapTrackPatchReplaceOperation
143 {
144   bool _isInstrumentMod;
145   WorkingDrumMapPatchList* _workingItemPatchList;
146   // Track to apply to.
147   MidiTrack* _track;
148 };
149 
150 // New items created in GUI thread awaiting addition in audio thread.
151 struct PendingOperationItem
152 {
153   enum PendingOperationType {
154     Uninitialized = 0,
155     ModifySongLength,
156     AddMidiInstrument, DeleteMidiInstrument, ReplaceMidiInstrument,
157     AddMidiDevice,     DeleteMidiDevice,
158     ModifyMidiDeviceAddress,         ModifyMidiDeviceFlags,       ModifyMidiDeviceName,
159     SetInstrument,
160     AddTrack,          DeleteTrack,  MoveTrack,                   ModifyTrackName,
161     SetTrackRecord, SetTrackMute, SetTrackSolo, SetTrackRecMonitor, SetTrackOff,
162     ModifyTrackDrumMapItem, ReplaceTrackDrumMapPatchList,         UpdateDrumMaps,
163     AddPart,           DeletePart,   MovePart, SelectPart, ModifyPartStart, ModifyPartLength,  ModifyPartName,
164     AddEvent,          DeleteEvent,  SelectEvent,  ModifyEventList,
165 
166     AddMidiCtrlVal,    DeleteMidiCtrlVal,     ModifyMidiCtrlVal,  AddMidiCtrlValList,
167     ModifyMidiCtrlValList,
168 
169     RemapDrumControllers,
170     AddAudioCtrlVal,   DeleteAudioCtrlVal,    ModifyAudioCtrlVal, ModifyAudioCtrlValList,
171     ModifyTempoList,   SetStaticTempo,        SetGlobalTempo,
172     ModifySigList,
173     ModifyKeyList,
174 
175     ModifyDefaultAudioConverterSettings, ModifyLocalAudioConverterSettings, ModifyLocalAudioConverter,
176     SetAudioConverterOfflineMode,
177     AddStretchListRatioAt,   DeleteStretchListRatioAt,  ModifyStretchListRatioAt,
178     ModifyStretchListRatio,
179 
180     AddAuxSendValue,
181     AddRoute,          DeleteRoute,
182     AddRouteNode,      DeleteRouteNode,       ModifyRouteNode,
183     UpdateSoloStates,
184     EnableAllAudioControllers,
185     GlobalSelectAllEvents,
186     ModifyAudioSamples,
187     SwitchMetronomeSettings, ModifyMetronomeAccentMap,
188     SetExternalSyncFlag, SetUseJackTransport, SetUseMasterTrack,
189     ModifyMarkerList
190     };
191 
192   PendingOperationType _type;
193 
194   union {
195     Part* _part;
196     MidiPort* _midi_port;
197     void* _void_track_list;
198     int* _audioSamplesLen;
199   };
200 
201   union {
202     EventList* _orig_event_list;
203     MidiCtrlValList* _orig_mcvl;
204     MidiCtrlValListList* _mcvll;
205     CtrlListList* _aud_ctrl_list_list;
206     TempoList* _orig_tempo_list;
207     MusECore::SigList* _orig_sig_list;
208     KeyList* _orig_key_list;
209     StretchList* _stretch_list;
210     PartList* _part_list;
211     TrackList* _track_list;
212     MidiDeviceList* _midi_device_list;
213     MidiInstrumentList* _midi_instrument_list;
214     AuxSendValueList* _aux_send_value_list;
215     RouteList* _route_list;
216     MarkerList** _orig_marker_list;
217     float** _audioSamplesPointer;
218     MetroAccentsMap** _metroAccentsMap;
219   };
220 
221   union {
222     EventList* _event_list;
223     MidiInstrument* _midi_instrument;
224     MidiDevice* _midi_device;
225     Track* _track;
226     MidiCtrlValList* _mcvl;
227     CtrlList* _aud_ctrl_list;
228     MarkerList* _marker_list;
229     TempoList* _tempo_list;
230     MusECore::SigList* _sig_list;
231     KeyList* _key_list;
232     Route* _dst_route_pointer;
233     float* _newAudioSamples;
234     bool* _bool_pointer;
235     MetroAccentsMap* _newMetroAccentsMap;
236     AudioConverterSettingsGroup* _audio_converter_settings;
237   };
238 
239   iPart _iPart;
240   Event _ev;
241   iEvent _iev;
242   iMidiCtrlVal _imcv;
243   iCtrl _iCtrl;
244   iCtrlList _iCtrlList;
245   iStretchListItem _iStretchEvent;
246   iMidiInstrument _iMidiInstrument;
247   iMidiDevice _iMidiDevice;
248   iRoute _iRoute;
249   iMarker _iMarker;
250   Route _src_route;
251   Route _dst_route;
252   // SndFileR is only 8 bytes but can't be in a union becuase of non-trivial destructor (?).
253   SndFileR _sndFileR;
254 
255   union {
256     int _intA;
257     unsigned int _uintA;
258     unsigned int _posLenVal;
259     bool _boolA;
260     const QString *_name;
261     double _aux_send_value;
262     int _insert_at;
263     int _from_idx;
264     int _address_client;
265     int _rw_flags;
266     int _newAudioSamplesLen;
267     //DrumMapOperation* _drum_map_operation;
268     DrumMapTrackOperation* _drum_map_track_operation;
269     DrumMapTrackPatchOperation* _drum_map_track_patch_operation;
270     DrumMapTrackPatchReplaceOperation* _drum_map_track_patch_replace_operation;
271     MidiCtrlValRemapOperation* _midi_ctrl_val_remap_operation;
272     MuseFrame_t _museFrame;
273     AudioConverterPluginI* _audio_converter;
274   };
275 
276   union {
277     int _intB;
278     unsigned int _uintB;
279     unsigned int _lenVal;
280     unsigned int _marker_tick;
281     int _to_idx;
282     int _address_port;
283     int _open_flags;
284     int _ctl_num;
285     int _stretch_type;
286     AudioConverterPluginI* _audio_converter_ui;
287   };
288 
289   union {
290     int _intC;
291     unsigned int _uintC;
292     int _ctl_val;
293     double _ctl_dbl_val;
294     double _audio_converter_value;
295     bool _marker_lock;
296   };
297 
298   PendingOperationItem(AudioConverterSettingsGroup* new_settings,
299                        PendingOperationType type = ModifyDefaultAudioConverterSettings)
300     { _type = type; _audio_converter_settings = new_settings; }
301 
302   PendingOperationItem(SndFileR sf, AudioConverterSettingsGroup* new_settings,
303                        PendingOperationType type = ModifyLocalAudioConverterSettings)
304     { _type = type; _sndFileR = sf;
305       _audio_converter_settings = new_settings; }
306 
307   PendingOperationItem(SndFileR sf,
308                        AudioConverterPluginI* newAudioConverter,
309                        AudioConverterPluginI* newAudioConverterUI,
310                        PendingOperationType type = ModifyLocalAudioConverter)
311     { _type = type; _sndFileR = sf;
312       _audio_converter = newAudioConverter;
313       _audio_converter_ui = newAudioConverterUI; }
314 
315   PendingOperationItem(SndFileR sf, AudioConverterPluginI* newAudioConverter,
316                        PendingOperationType type = SetAudioConverterOfflineMode)
317     { _type = type; _sndFileR = sf; _audio_converter = newAudioConverter; }
318 
319 
320   PendingOperationItem(float** samples, float* new_samples, int* samples_len, int new_samples_len,
321                        PendingOperationType type = ModifyAudioSamples)
322     { _type = type; _audioSamplesPointer = samples; _newAudioSamples = new_samples;
323       _audioSamplesLen = samples_len, _newAudioSamplesLen = new_samples_len; }
324 
325 
326   // The operation is constructed and allocated in non-realtime before the call, then the controllers modified in realtime stage,
327   //  then operation is deleted in non-realtime stage.
328   PendingOperationItem(MidiCtrlValRemapOperation* operation, PendingOperationType type = RemapDrumControllers)
329     { _type = type; _midi_ctrl_val_remap_operation = operation; }
330 
331   // The operation is constructed and allocated in non-realtime before the call, then the track's map is modified in realtime stage,
332   //  then operation is deleted in non-realtime stage.
333   PendingOperationItem(DrumMapTrackOperation* operation, PendingOperationType type = ModifyTrackDrumMapItem)
334     { _type = type; _drum_map_track_operation = operation; }
335 
336   // The operation is constructed and allocated in non-realtime before the call, then the track's map is modified in realtime stage,
337   //  then operation is deleted in non-realtime stage.
338   PendingOperationItem(DrumMapTrackPatchReplaceOperation* operation, PendingOperationType type = ReplaceTrackDrumMapPatchList)
339     { _type = type; _drum_map_track_patch_replace_operation = operation; }
340 
341   PendingOperationItem(MidiPort* mp, PendingOperationType type = UpdateDrumMaps)
342     { _type = type; _midi_port = mp; }
343 
344   PendingOperationItem(TrackList* tl, PendingOperationType type = UpdateSoloStates)
345     { _type = type; _track_list = tl; }
346 
347   // TODO: Try to break this operation down so that only the actual operation is executed stage-2.
PendingOperationItemPendingOperationItem348   PendingOperationItem(const Route& src_route, const Route& dst_route, PendingOperationType type) // Type is AddRoute or DeleteRoute.
349     { _type = type; _src_route = src_route; _dst_route = dst_route; }
350 
351   PendingOperationItem(RouteList* route_list, const Route& route, PendingOperationType type = AddRouteNode)
352     { _type = type; _route_list = route_list; _src_route = route; }
353 
354   PendingOperationItem(RouteList* route_list, const iRoute& ir, PendingOperationType type = DeleteRouteNode)
355     { _type = type; _route_list = route_list; _iRoute = ir; }
356 
357   PendingOperationItem(const Route& src_route, Route* dst_route, PendingOperationType type = ModifyRouteNode)
358     { _type = type; _src_route = src_route; _dst_route_pointer = dst_route; }
359 
360   PendingOperationItem(AuxSendValueList* asvl, double val, PendingOperationType type = AddAuxSendValue)
361     { _type = type; _aux_send_value_list = asvl; _aux_send_value = val; }
362 
363   PendingOperationItem(MidiInstrumentList* mil, MidiInstrument* midi_instrument, PendingOperationType type = AddMidiInstrument)
364     { _type = type; _midi_instrument_list = mil; _midi_instrument = midi_instrument; }
365 
366   PendingOperationItem(MidiInstrumentList* mil, const iMidiInstrument& imi, PendingOperationType type = DeleteMidiInstrument)
367     { _type = type; _midi_instrument_list = mil; _iMidiInstrument = imi; }
368 
369   PendingOperationItem(MidiInstrumentList* mil, const iMidiInstrument& imi, MidiInstrument* new_instrument,
370                        PendingOperationType type = ReplaceMidiInstrument)
371     { _type = type; _midi_instrument_list = mil; _iMidiInstrument = imi; _midi_instrument = new_instrument; }
372 
373   PendingOperationItem(MidiDeviceList* mdl, MidiDevice* midi_device, PendingOperationType type = AddMidiDevice)
374     { _type = type; _midi_device_list = mdl; _midi_device = midi_device; }
375 
376   PendingOperationItem(MidiDeviceList* mdl, const iMidiDevice& imd, PendingOperationType type = DeleteMidiDevice)
377     { _type = type; _midi_device_list = mdl; _iMidiDevice = imd; }
378 
379   // Type is ModifyMidiDeviceAddress or ModifyMidiDeviceFlags
PendingOperationItemPendingOperationItem380   PendingOperationItem(MidiDevice* midi_device, int address_client_or_rw_flags, int address_port_or_open_flags, PendingOperationType type)
381     { _type = type; _midi_device = midi_device; _intA = address_client_or_rw_flags; _intB = address_port_or_open_flags; }
382 
383   PendingOperationItem(MidiDevice* midi_device, const QString* new_name, PendingOperationType type = ModifyMidiDeviceName)
384     { _type = type; _midi_device = midi_device; _name = new_name; }
385 
386 
387   PendingOperationItem(MidiPort* midi_port, MidiInstrument* midi_instrument, PendingOperationType type = SetInstrument)
388     { _type = type; _midi_port = midi_port; _midi_instrument = midi_instrument; }
389 
390 
391   PendingOperationItem(TrackList* tl, Track* track, int insert_at, PendingOperationType type = AddTrack, void* sec_track_list = 0)
392     { _type = type; _track_list = tl; _track = track; _insert_at = insert_at; _void_track_list = sec_track_list; }
393 
394   PendingOperationItem(TrackList* tl, Track* track, PendingOperationType type = DeleteTrack, void* sec_track_list = 0)
395     { _type = type; _track_list = tl; _track = track; _void_track_list = sec_track_list; }
396 
397   PendingOperationItem(TrackList* tl, int from_idx, int to_idx, PendingOperationType type = MoveTrack)
398     { _type = type; _track_list = tl; _from_idx = from_idx; _to_idx = to_idx; }
399 
400   PendingOperationItem(TrackList* tl, bool select, unsigned long /*t0*/, unsigned long /*t1*/,
401                        PendingOperationType type = GlobalSelectAllEvents)
402     { _type = type; _track_list = tl;
403         _boolA = select; }
404 
405   PendingOperationItem(Track* track, const QString* new_name, PendingOperationType type = ModifyTrackName)
406     { _type = type; _track = track; _name = new_name; }
407 
408    // type is SetTrackRecord, SetTrackMute, SetTrackSolo, SetTrackRecMonitor, SetTrackOff
PendingOperationItemPendingOperationItem409   PendingOperationItem(Track* track, bool v, PendingOperationType type)
410     { _type = type; _track = track; _boolA = v; }
411 
412 
413   PendingOperationItem(Part* part, const QString* new_name, PendingOperationType type = ModifyPartName)
414     { _type = type; _part = part; _name = new_name; }
415 
416   PendingOperationItem(Part* part, bool v, PendingOperationType type = SelectPart)
417     { _type = type; _part = part; _boolA = v; }
418 
419   // new_pos and new_len must already be in the part's time domain (ticks or frames).
420   // The new_event_list can be set to null, or if the part's events are to be dragged with the border
421   //  it can be supplied to do a wholesale fast constant-time swap of the event lists.
422   PendingOperationItem(iPart ip, Part* part, unsigned int new_pos, unsigned int new_len,
423                        EventList* new_event_list, PendingOperationType type = ModifyPartStart)
424     { _type = type; _iPart = ip, _part = part; _event_list = new_event_list; _posLenVal = new_pos; _lenVal = new_len; }
425 
426   // new_len must already be in the part's time domain (ticks or frames).
427   // The new_event_list can be set to null, or if the part's events are to be dragged with the border
428   //  it can be supplied to do a wholesale fast constant-time swap of the event lists.
429   PendingOperationItem(iPart ip, Part* part, unsigned int new_len, EventList* new_event_list, PendingOperationType type = ModifyPartLength)
430     { _type = type; _iPart = ip, _part = part; _event_list = new_event_list; _posLenVal = new_len; }
431 
432   // Erases ip from part->track()->parts(), then adds part to new_track. NOTE: ip may be part->track()->parts()->end().
433   // new_pos must already be in the part's time domain (ticks or frames).
434   PendingOperationItem(iPart ip, Part* part, unsigned int new_pos, PendingOperationType type = MovePart, Track* new_track = 0)
435     { _type = type; _iPart = ip; _part = part; _track = new_track;
436         _posLenVal = new_pos;}
437 
438   PendingOperationItem(PartList* pl, Part* part, PendingOperationType type = AddPart)
439     { _type = type; _part_list = pl; _part = part; }
440 
441   PendingOperationItem(PartList* pl, const iPart& ip, PendingOperationType type = DeletePart)
442     { _type = type; _part_list = pl; _iPart = ip; }
443 
444 
445   PendingOperationItem(Part* part, const Event& ev, PendingOperationType type = AddEvent)
446     { _type = type; _part = part; _ev = ev; }
447 
448   // NOTE: To avoid possibly deleting the event in RT stage 2 when the event is erased from the list,
449   //        _ev is used simply to hold a reference until non-RT stage 3 or after, when the list is cleared.
450   PendingOperationItem(Part* part, const iEvent& iev, PendingOperationType type = DeleteEvent)
451     { _type = type; _part = part; _iev = iev; _ev = iev->second; }
452 
453   // Type is SelectEvent, or some (likely) future boolean operation.
PendingOperationItemPendingOperationItem454   PendingOperationItem(Part* part, const Event& ev, int v, PendingOperationType type)
455     { _type = type; _part = part; _ev = ev; _intA = v; }
456 
457 
458   PendingOperationItem(MidiCtrlValListList* mcvll, MidiCtrlValList* mcvl, int channel, int control_num, PendingOperationType type = AddMidiCtrlValList)
459     { _type = type; _mcvll = mcvll; _mcvl = mcvl; _intA = channel; _intB = control_num; }
460 
461   PendingOperationItem(const iCtrlList& ictl_l, CtrlList* ctrl_l, PendingOperationType type = ModifyAudioCtrlValList)
462     { _type = type; _iCtrlList = ictl_l; _aud_ctrl_list = ctrl_l; }
463 
464   PendingOperationItem(MidiCtrlValList* mcvl, Part* part, unsigned int tick, int val, PendingOperationType type = AddMidiCtrlVal)
465     { _type = type; _mcvl = mcvl; _part = part;
466         _posLenVal = tick; _intB = val; }
467 
468   PendingOperationItem(MidiCtrlValList* mcvl, const iMidiCtrlVal& imcv, PendingOperationType type = DeleteMidiCtrlVal)
469     { _type = type; _mcvl = mcvl; _imcv = imcv; }
470 
471   // NOTE: mcvl is supplied in case the operation needs to be merged, or transformed into an AddMidiCtrlVal.
472   PendingOperationItem(MidiCtrlValList* mcvl, const iMidiCtrlVal& imcv, int val, PendingOperationType type = ModifyMidiCtrlVal)
473     { _type = type; _mcvl = mcvl; _imcv = imcv; _intA = val; }
474 
475 
476   PendingOperationItem(MidiCtrlValList* orig_mcvl, MidiCtrlValList* mcvl, PendingOperationType type = ModifyMidiCtrlValList)
477     { _type = type; _orig_mcvl = orig_mcvl; _mcvl = mcvl; }
478 
479   PendingOperationItem(CtrlList* ctrl_l, unsigned int frame, double ctrl_val, PendingOperationType type = AddAudioCtrlVal)
480     { _type = type; _aud_ctrl_list = ctrl_l; _posLenVal = frame; _ctl_dbl_val = ctrl_val; }
481 
482   PendingOperationItem(CtrlList* ctrl_l, const iCtrl& ictl, PendingOperationType type = DeleteAudioCtrlVal)
483     { _type = type; _aud_ctrl_list = ctrl_l; _iCtrl = ictl; }
484 
485   // NOTE: ctrl_l is supplied in case the operation needs to be merged, or transformed into an AddAudioCtrlVal.
486   PendingOperationItem(CtrlList* ctrl_l, const iCtrl& ictl, unsigned int new_frame,
487                        double new_ctrl_val, PendingOperationType type = ModifyAudioCtrlVal)
488     { _type = type; _aud_ctrl_list = ctrl_l; _iCtrl = ictl; _posLenVal = new_frame; _ctl_dbl_val = new_ctrl_val; }
489 
490 
491   // Takes ownership of the original list so it can be deleted in the non-RT stage.
492   PendingOperationItem(TempoList* orig_tempo_l, TempoList* new_tempo_l, PendingOperationType type = ModifyTempoList)
493     { _type = type; _orig_tempo_list = orig_tempo_l; _tempo_list = new_tempo_l; }
494 
495   // type is SetGlobalTempo, SetStaticTempo.
PendingOperationItemPendingOperationItem496   PendingOperationItem(TempoList* tl, int tempo, PendingOperationType type)
497     { _type = type; _tempo_list = tl; _intA = tempo; }
498 
499   PendingOperationItem(TempoList* tl, bool v, PendingOperationType type = SetUseMasterTrack)
500     { _type = type; _tempo_list = tl; _boolA = v; }
501 
502 
503   // Takes ownership of the original list so it can be deleted in the non-RT stage.
504   PendingOperationItem(SigList* orig_sig_l, SigList* new_sig_l, PendingOperationType type = ModifySigList)
505     { _type = type; _orig_sig_list = orig_sig_l; _sig_list = new_sig_l; }
506 
507 
508   // Takes ownership of the original list so it can be deleted in the non-RT stage.
509   PendingOperationItem(KeyList* orig_key_l, KeyList* new_key_l, PendingOperationType type = ModifyKeyList)
510     { _type = type; _orig_key_list = orig_key_l; _key_list = new_key_l; }
511 
512 
513   PendingOperationItem(int stretchType, StretchList* sl, MuseFrame_t frame, double ratio, PendingOperationType type = AddStretchListRatioAt)
514     { _type = type; _stretch_type = stretchType, _stretch_list = sl; _museFrame = frame; _audio_converter_value = ratio; }
515 
516   PendingOperationItem(int stretchTypes, StretchList* sl, const iStretchListItem& ise, PendingOperationType type = DeleteStretchListRatioAt)
517     { _type = type; _stretch_type = stretchTypes, _stretch_list = sl; _iStretchEvent = ise; }
518 
519   PendingOperationItem(int stretchType, StretchList* sl, const iStretchListItem& ise, MuseFrame_t new_frame, double ratio,
520                        PendingOperationType type = ModifyStretchListRatioAt)
521     { _type = type; _stretch_type = stretchType, _stretch_list = sl; _iStretchEvent = ise;
522       _museFrame = new_frame; _audio_converter_value = ratio; }
523 
524   PendingOperationItem(int stretchType, StretchList* sl, double ratio, PendingOperationType type = ModifyStretchListRatio)
525     { _type = type; _stretch_type = stretchType, _stretch_list = sl; _audio_converter_value = ratio; }
526 
527 
528   PendingOperationItem(unsigned int len, PendingOperationType type = ModifySongLength)
529     { _type = type; _posLenVal = len; }
530 
531   PendingOperationItem(MetroAccentsMap** old_map, MetroAccentsMap* new_map, PendingOperationType type = ModifyMetronomeAccentMap)
532     { _type = type; _metroAccentsMap = old_map; _newMetroAccentsMap = new_map; }
533 
534   // Type is SwitchMetronomeSettings, SetExternalSyncFlag, SetUseJackTransport.
PendingOperationItemPendingOperationItem535   PendingOperationItem(bool* bool_pointer, bool v, PendingOperationType type)
536     { _type = type; _bool_pointer = bool_pointer; _boolA = v; }
537 
PendingOperationItemPendingOperationItem538   PendingOperationItem(PendingOperationType type) // type is EnableAllAudioControllers.
539     { _type = type; }
540 
541   // Takes ownership of the original list so it can be deleted in the non-RT stage.
542   PendingOperationItem(MarkerList** orig_marker_l, MarkerList* new_marker_l, PendingOperationType type = ModifyMarkerList)
543     { _type = type; _orig_marker_list = orig_marker_l; _marker_list = new_marker_l; }
544 
PendingOperationItemPendingOperationItem545   PendingOperationItem()
546     { _type = Uninitialized; }
547 
548   // Execute the operation. Called only from RT stage 2.
549     SongChangedStruct_t executeRTStage();
550   // Execute the operation. Called only from post RT stage 3.
551     SongChangedStruct_t executeNonRTStage();
552   // Get an appropriate indexing value from ops like AddEvent that use it. Other ops like AddMidiCtrlValList return their type (rather than say, zero).
553   unsigned int getIndex() const;
554   // Whether the two special allocating ops (like AddMidiCtrlValList) are the same.
555   // The comparison ignores the actual allocated value, so that such commands can be found before they do their allocating.
556   bool isAllocationOp(const PendingOperationItem&) const;
557 };
558 
559 class PendingOperationList : public std::list<PendingOperationItem>
560 {
561   private:
562     // Holds sorted version of list. Index is time value for items which have it like events or parts,
563     //  otherwise it is the operation type for other items. It doesn't matter too much that ticks and frames
564     //  are mixed here, sorting by time is just to speed up searches, we look for operation types.
565     std::multimap<unsigned int, iterator, std::less<unsigned int> > _map;
566     // Accumulated song changed flags.
567     SongChangedStruct_t _sc_flags;
568 
569   public:
PendingOperationList()570     PendingOperationList() : _sc_flags(0) { }
571     // Add an operation. Returns false if the operation already exists or could not be added
572     //  (such as with a DeleteEvent being cancelled by an AddEvent on identical base events),
573     //  or various other optimizations that essentially render the operation ineffectual.
574     // Some operations optimize by replacing an existing operation with the requested one.
575     // For example requesting operations which simply change a value replace any existing
576     //  such operation with the requested new value. Thus only one operation exists - the LATEST.
577     // Returns true in those cases so that the caller can proceed to perform other operations
578     //  on the item even though the operation was not officially added to the list (it replaced one).
579     // Otherwise returns true. Optimizes all added items (merge, discard, alter, embellish etc.)
580     bool add(PendingOperationItem);
581     // Execute the RT portion of the operations contained in the list. Called only from RT stage 2.
582     SongChangedStruct_t executeRTStage();
583     // Execute the Non-RT portion of the operations contained in the list. Called only from post RT stage 3.
584     SongChangedStruct_t executeNonRTStage();
585     // Clear both the list and the map, and flags.
586     void clear();
587     // Returns the accumulated song changed flags.
flags()588     SongChangedStruct_t flags() const { return _sc_flags; }
589     // Find an existing special allocation command (like AddMidiCtrlValList).
590     // The comparison ignores the actual allocated value, so that such commands can be found before they do their allocating.
591     iterator findAllocationOp(const PendingOperationItem& op);
592 
593 
594     void addDeviceOperation(MidiDeviceList* devlist, MidiDevice* dev);
595 
596     void addTrackPortCtrlEvents(Track* track);
597     void removeTrackPortCtrlEvents(Track* track);
598 
599     void addPartPortCtrlEvents(
600       const Event& event, Part* part, unsigned int tick, unsigned int /*len*/, Track* track);
601     void addPartPortCtrlEvents(Part* part, unsigned int tick, unsigned int len, Track* track);
602     bool removePartPortCtrlEvents(const Event& event, Part* part, Track* track);
603     void removePartPortCtrlEvents(Part* part, Track* track);
604     void modifyPartPortCtrlEvents(const Event& old_event, const Event& event, Part* part);
605 
606     void addPartOperation(PartList *partlist, Part* part);
607     void delPartOperation(PartList *partlist, Part* part);
608     void movePartOperation(PartList *partlist, Part* part, unsigned int new_pos, Track* track = 0);
609     void modifyPartStartOperation(Part* part, unsigned int new_pos, unsigned int new_len, int64_t events_offset, Pos::TType events_offset_time_type);
610     void modifyPartLengthOperation(Part* part, unsigned int new_len, int64_t events_offset, Pos::TType events_offset_time_type);
611 
612     void addTrackAuxSendOperation(AudioTrack *atrack, int n);
613 
614     //void TrackMidiCtrlRemapOperation(int index, int newPort, int newChan, int newNote, MidiCtrlValRemapOperation* rmop);
615 };
616 
617 typedef PendingOperationList::iterator iPendingOperation;
618 typedef std::multimap<unsigned int, iPendingOperation, std::less<unsigned int> >::iterator iPendingOperationSorted;
619 typedef std::multimap<unsigned int, iPendingOperation, std::less<unsigned int> >::reverse_iterator riPendingOperationSorted;
620 typedef std::pair <iPendingOperationSorted, iPendingOperationSorted> iPendingOperationSortedRange;
621 
622 extern void TrackMidiCtrlRemapOperation(
623   MidiTrack *mtrack, int index, int newPort, int newChan, int newNote, MidiCtrlValRemapOperation* rmop);
624 
625 } // namespace MusECore
626 
627 #endif
628