1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: midictrl.h,v 1.16.2.8 2009/11/25 09:09:43 terminator356 Exp $
5 //
6 //  (C) Copyright 1999-2003 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)
8 //
9 //  This program is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public License
11 //  as published by the Free Software Foundation; version 2 of
12 //  the License, or (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU General Public License for more details.
18 //
19 //  You should have received a copy of the GNU General Public License
20 //  along with this program; if not, write to the Free Software
21 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 //=========================================================
24 
25 #ifndef __MIDI_CONTROLLER_H__
26 #define __MIDI_CONTROLLER_H__
27 
28 #include <map>
29 
30 #include <QString>
31 
32 #include "midictrl_consts.h"
33 #include "xml.h"
34 
35 //#define _MIDI_CTRL_DEBUG_
36 // For finding exactly who may be calling insert, erase clear etc. in
37 //  the controller list classes. (KDevelop 'Find uses'.)
38 //#define _MIDI_CTRL_METHODS_DEBUG_
39 
40 namespace MusECore {
41 
42 //---------------------------------------------------------
43 //   MidiController
44 //---------------------------------------------------------
45 
46 class MidiController {
47    public:
48       //
49       // mapping of midi controller types to
50       // controller number:
51       //
52       enum ControllerType {
53             Controller7,      // num values from 0 - 0x7f
54             Controller14,     // values from 0x10000 - 0x12fff
55             RPN,              // registered parameter 0x20000 -
56             NRPN,             // non registered parameter 0x30000 -
57             RPN14,            // registered parameter 0x50000
58             NRPN14,           // non registered parameter 0x60000 -
59             Pitch,            // num value = CTRL_PITCH
60             Program,          // num value = CTRL_PROGRAM
61             PolyAftertouch,   // num value = CTRL_POLYAFTER
62             Aftertouch,       // num value = CTRL_AFTERTOUCH
63             Velo              // not assigned
64             };
65 
66       enum ShowInTrackType { ShowInDrum=1, ShowInMidi=2 };
67 
68    protected:
69       QString _name;
70       int _num;               // Controller Number
71       int _minVal;            // controller value range (used in gui)
72       int _maxVal;
73       int _initVal;
74       // Special for drum mode, for controllers such as program.
75       int _drumInitVal;
76       int _bias;
77       int _showInTracks;
78       void updateBias();
79 
80    public:
81       MidiController();
82       // If drumInit = -1, it means don't care - use the init val.
83       MidiController(const QString& n, int num, int min, int max, int init, int drumInit, int show_in_track = (ShowInDrum | ShowInMidi));
84       MidiController(const MidiController& mc);
85       void copy(const MidiController &mc);
86       MidiController& operator= (const MidiController &mc);
87 
88       // Convert given controller double value to integer.
dValToInt(double v)89       static inline int dValToInt(double v) {
90         // TODO: Decide best choice here.
91         //return int(round(v));
92         //return lrint(v);
93         return int(v);
94       }
95 
96       // Whether the given integer value is CTRL_VAL_UNKNOWN.
iValIsUnknown(int v)97       static inline bool iValIsUnknown(int v) { return v == CTRL_VAL_UNKNOWN; }
98       // Whether the given double value is CTRL_VAL_UNKNOWN.
dValIsUnknown(double v)99       static inline bool dValIsUnknown(double v) { return iValIsUnknown(dValToInt(v)); }
100 
name()101       const QString& name() const         { return _name;   }
num()102       int num() const                     { return _num;    }
103       ControllerType type() const;
setName(const QString & s)104       void setName(const QString& s)      { _name = s;      }
setNum(int v)105       void setNum(int v)                  { _num = v;       }
106       void write(int level, Xml& xml) const;
107       void read(Xml& xml);
minVal()108       int minVal() const                  { return _minVal; }
maxVal()109       int maxVal() const                  { return _maxVal; }
initVal()110       int initVal() const                 { return _initVal; }
initValIsUnknown()111       inline bool initValIsUnknown() const { return iValIsUnknown(_initVal); }
setInitVal(int val)112       void setInitVal(int val)            { _initVal = val; }
drumInitVal()113       int drumInitVal() const             { return _drumInitVal; }
drumInitValIsUnknown()114       inline bool drumInitValIsUnknown() const { return iValIsUnknown(_drumInitVal); }
setDrumInitVal(int val)115       void setDrumInitVal(int val)        { _drumInitVal = val; }
setMinVal(int val)116       void setMinVal(int val)             { _minVal = val; updateBias(); }
setMaxVal(int val)117       void setMaxVal(int val)             { _maxVal = val; updateBias(); }
bias()118       int bias() const                    { return _bias; }
showInTracks()119       int showInTracks() const            { return _showInTracks; }
setShowInTracks(int i)120       void setShowInTracks(int i)         { _showInTracks = i; }
121       bool isPerNoteController() const;
122       static int genNum(ControllerType, int, int);
123       };
124 
125 
126 //---------------------------------------------------------
127 //   MidiControllerList
128 //    this is a list of used midi controllers created
129 //    - explicit by user
130 //    - implicit during import of a midi file
131 //---------------------------------------------------------
132 
133 typedef std::map<int, MidiController*, std::less<int> > MidiControllerList_t;
134 
135 class MidiControllerList : public MidiControllerList_t
136 {
137       bool _RPN_Ctrls_Reserved;
138 
139    public:
140       MidiControllerList();
141       MidiControllerList(const MidiControllerList& mcl);
142       // NOTE: There is no destructor here, this container does not
143       //        delete its own contents, that is done in ~MidiInstrument
144       //        because some controls are shared (the ones in
145       //        defaultMidiController and defaultManagedMidiController).
146       //       However, an inheritor such as the class MidiNamCtrls
147       //        found in the MidNam module DOES delete its own.
148 
149       // Like find() which finds a verbose ctl number, but this version also finds a per-note
150       //  controller if there is one for the given ctl number, if no verbose one was found.
151       // Returns null if no controller found. The ctl number can be the 'real' controller number,
152       //  ie the low byte can be the actual note number and does not have to be 0xff.
153       MidiController* findController(int ctl) const;
154       // Returns per-note controller if there is one for the given ctl number.
155       // Otherwise returns null. The ctl number can be the 'real' controller number,
156       //  ie the low byte can be the actual note number and does not have to be 0xff.
157       MidiController* perNoteController(int ctl) const;
158 
159       // Like 'find', finds a controller given fully qualified type + number.
160       // But it returns controller with highest priority if multiple controllers use the
161       //  given number such as {Controller7, num = 0x55} + {Controller14, num = 0x5544}.
162       // Note if given number is one of the eight reserved General Midi (N)RPN controllers,
163       //  this will only return Controller7 or Controller14, not anything (N)RPN related.
164       // That is, it will not 'encode' (N)RPNs. Use a MidiEncoder instance for that.
165       iterator searchControllers(int ctl);
166       // Check if either a per-note controller, or else a regular controller already exists.
167       bool ctrlAvailable(int find_num, MidiController* ignore_this = 0);
168       // Returns true if any of the EIGHT reserved General Midi (N)RPN control numbers are
169       //  ALREADY defined as Controller7 or part of Controller14. Cached, for speed.
170       // Used (at least) by midi input encoders to quickly arbitrate new input.
RPN_Ctrls_Reserved()171       bool RPN_Ctrls_Reserved() { return _RPN_Ctrls_Reserved; }
172       // Manual check and update of the flag. For convenience, returns the flag.
173       bool update_RPN_Ctrls_Reserved();
174 
175       // NOTICE: If update is false or these are bypassed by using insert, erase, clear etc. for speed,
176       //          then BE SURE to call update_RPN_Ctrls_Reserved() later.
177       // Returns true if add is successful.
178       bool add(MidiController* mc, bool update = true);
179       void del(iterator ictl, bool update = true);
180       size_type del(int num, bool update = true);
181       void del(iterator first, iterator last, bool update = true);
182       void clr();
183 
184 #ifdef _MIDI_CTRL_METHODS_DEBUG_
185       // Need to catch all insert, erase, clear etc...
186       void swap(MidiControllerList&);
187       std::pair<iterator, bool> insert(const std::pair<int, MidiController*>& p);
188       iterator insert(iterator ic, const std::pair<int, MidiController*>& p);
189       void erase(iterator ictl);
190       size_type erase(int num);
191       void erase(iterator first, iterator last);
192       void clear();
193 #endif
194       // Some IDEs won't "Find uses" of operators. So, no choice but to trust always catching it here.
195       MidiControllerList& operator=(const MidiControllerList&);
196 };
197 
198 typedef MidiControllerList::iterator iMidiController;
199 typedef MidiControllerList::const_iterator ciMidiController;
200 typedef std::pair<int /* number */, MidiController*> MidiControllerListPair;
201 
202 extern MidiController::ControllerType midiControllerType(int num);
203 extern int midiCtrlTerms2Number(MidiController::ControllerType type, int ctrl = 0);
204 extern bool isPerNoteMidiController(int num);
205 
206 
207 extern const QString& int2ctrlType(int n);
208 extern MidiController::ControllerType ctrlType2Int(const QString& s);
209 extern QString midiCtrlName(int ctrl, bool fullyQualified = false);
210 extern QString midiCtrlNumString(int ctrl, bool fullyQualified = false);
211 
212 typedef std::map<int, int, std::less<int> > MidiCtl2LadspaPortMap;
213 typedef MidiCtl2LadspaPortMap::iterator iMidiCtl2LadspaPort;
214 typedef MidiCtl2LadspaPortMap::const_iterator ciMidiCtl2LadspaPort;
215 
216 
217 // // REMOVE Tim. midnam. Added.
218 // // template<class Key, class T, class Compare = std::less<Key>,
219 // //          class Alloc = std::allocator<std::pair<const Key,T> > >
220 // //   class CompoundMidiControllerList_t : public MidiControllerList_t
221 //   class CompoundMidiControllerList_t : public MidiControllerList
222 // {
223 //   private:
224 // //     typedef std::multimap<Key, T, Compare, Alloc> vlist;
225 // //     typedef MidiControllerList_t vlist;
226 //     typedef MidiControllerList vlist;
227 //     //typedef typename std::list<T>::const_iterator cil_t;
228 //
229 //     //MidiControllerList** _p_other;
230 //     //MidNamMIDIName* _midnamDocument;
231 //
232 //   protected:
233 //     //Pos::TType _type;
234 //     MidiControllerList** _p_other;
235 //
236 //   public:
237 //     typedef typename vlist::iterator iCompoundMidiControllerList_t;
238 //     typedef typename vlist::const_iterator ciCompoundMidiControllerList_t;
239 // //     typedef std::pair <ciMixedPosList_t, ciMixedPosList_t> cMixedPosListRange_t;
240 // //     typedef std::pair <Key, T> MixedPosListInsertPair_t;
241 //     typedef std::pair <int, MidiController*> CompoundMidiControllerListInsertPair_t;
242 //
243 //
244 //     class iterator : public vlist::iterator {
245 //         protected:
246 //           const MidiControllerList* _p_list;
247 //           MidiControllerList** _p_other;
248 //           bool _isFromOther;
249 //
250 //         public:
251 //           iterator() : vlist::iterator(), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
252 //           iterator(vlist::iterator i) : vlist::iterator(i), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
253 //
254 //           void setLists(const MidiControllerList* this_list, MidiControllerList** other, bool isFromOther)
255 //             { _p_list = this_list; _p_other = other; _isFromOther = isFromOther; }
256 //
257 // //             MidiController* operator*() {
258 // //                   //return (MidiController*)(**((vlist::iterator*)this));
259 // //                   return (MidiController*)(**((vlist::iterator*)this->second));
260 // //                   }
261 //           iterator operator++(int) {
262 //                 return iterator ((*(vlist::iterator*)this).operator++(0));
263 //                 }
264 //           iterator& operator++() {
265 //                 vlist::iterator i_this = *this;
266 //                 i_this++;
267 //                 if(_p_other && !(*_p_other)->empty())
268 //                 {
269 //
270 //                 }
271 //
272 //                 (iterator&) ((*(vlist::iterator*)this).operator++())
273 //
274 //
275 //                 return (iterator&) ((*(vlist::iterator*)this).operator++());
276 //                 }
277 //           };
278 //
279 //     class const_iterator : public vlist::const_iterator {
280 //         protected:
281 //           const MidiControllerList* _p_list;
282 //           MidiControllerList** _p_other;
283 //           bool _isFromOther;
284 //
285 //         public:
286 //           const_iterator() : vlist::const_iterator(), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
287 //           const_iterator(vlist::const_iterator i)
288 //             : vlist::const_iterator(i), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
289 //           const_iterator(vlist::iterator i)
290 //             : vlist::const_iterator(i), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
291 //
292 //           void setLists(const MidiControllerList* this_list, MidiControllerList** other, bool isFromOther)
293 //             { _p_list = this_list; _p_other = other; _isFromOther = isFromOther; }
294 //
295 // //             const T operator*() const {
296 // //                   return (T)(**((vlist::const_iterator*)this));
297 // //                   }
298 //           std::pair <int, MidiController*> operator*() const {
299 //                 return **((vlist::const_iterator*)this);
300 //                 }
301 // //             const MidiController* operator->() const {
302 // //                   return (**((vlist::const_iterator*)this)->second);
303 // //                   }
304 //           };
305 //
306 //     class reverse_iterator : public vlist::reverse_iterator {
307 //         protected:
308 //           const MidiControllerList* _p_list;
309 //           MidiControllerList** _p_other;
310 //           bool _isFromOther;
311 //
312 //         public:
313 //           reverse_iterator() : vlist::reverse_iterator(), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
314 //           reverse_iterator(vlist::reverse_iterator i)
315 //             : vlist::reverse_iterator(i), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
316 //
317 //           void setLists(const MidiControllerList* this_list, MidiControllerList** other, bool isFromOther)
318 //             { _p_list = this_list; _p_other = other; _isFromOther = isFromOther; }
319 //
320 // //             T operator*() {
321 // //                   return (T)(**((vlist::reverse_iterator*)this));
322 // //                   }
323 //           std::pair <int, MidiController*> operator*() {
324 //                 return **((vlist::reverse_iterator*)this);
325 //                 }
326 //           };
327 //
328 //     class const_reverse_iterator : public vlist::const_reverse_iterator {
329 //         protected:
330 //           const MidiControllerList* _p_list;
331 //           MidiControllerList** _p_other;
332 //           bool _isFromOther;
333 //
334 //         public:
335 //           const_reverse_iterator() : vlist::const_reverse_iterator(), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
336 //           const_reverse_iterator(vlist::const_reverse_iterator i)
337 //             : vlist::const_reverse_iterator(i), _p_list(nullptr), _p_other(nullptr), _isFromOther(false) {}
338 //
339 //           void setLists(const MidiControllerList* this_list, MidiControllerList** other, bool isFromOther)
340 //             { _p_list = this_list; _p_other = other; _isFromOther = isFromOther; }
341 //
342 // //             T operator*() {
343 // //                   return (T)(**((vlist::const_reverse_iterator*)this));
344 // //                   }
345 //           std::pair <int, MidiController*> operator*() {
346 //                 return **((vlist::const_reverse_iterator*)this);
347 //                 }
348 //           };
349 //
350 //
351 //
352 //
353 //     //CompoundMidiControllerList_t(Pos::TType type = Pos::TICKS) : vlist(), _type(type) {}
354 //     CompoundMidiControllerList_t(MidiControllerList** other = nullptr)
355 //       : vlist(), _p_other(other) { }
356 //
357 //     virtual ~CompoundMidiControllerList_t() {}
358 //
359 //     //inline Pos::TType type() const { return _type; }
360 //     //inline void setType(const Pos::TType& t) { _type = t; rebuild(); }
361 //
362 //     iterator begin() noexcept
363 //     {
364 //       iterator i_this = vlist::begin();
365 //       i_this.setLists(this, _p_other, false);
366 //       if(_p_other && !(*_p_other)->empty())
367 //       {
368 //         iterator i_other = (*_p_other)->begin();
369 //         i_other.setLists(this, _p_other, true);
370 //         if(vlist::empty() || i_other->first < i_this->first)
371 //           return i_other;
372 //       }
373 //       return i_this;
374 //     }
375 //
376 //     const_iterator begin() const noexcept
377 //     {
378 //       const_iterator i_this = vlist::begin();
379 //       i_this.setLists(this, _p_other, false);
380 //       if(_p_other && !(*_p_other)->empty())
381 //       {
382 //         const MidiControllerList* mcl_other = *_p_other;
383 //         const_iterator i_other = mcl_other->begin();
384 //         i_other.setLists(this, _p_other, true);
385 //         if(vlist::empty() || i_other->first < i_this->first)
386 //           return i_other;
387 //       }
388 //       return i_this;
389 //     }
390 //
391 //     const_iterator cbegin() const noexcept
392 //     {
393 //       const_iterator i_this = vlist::cbegin();
394 //       i_this.setLists(this, _p_other, false);
395 //       if(_p_other && !(*_p_other)->empty())
396 //       {
397 //         const_iterator i_other = (*_p_other)->cbegin();
398 //         i_other.setLists(this, _p_other, true);
399 //         if(vlist::empty() || i_other->first < i_this->first)
400 //           return i_other;
401 //       }
402 //       return i_this;
403 //     }
404 //
405 //     reverse_iterator rbegin() noexcept
406 //     {
407 //       reverse_iterator i_this = vlist::rbegin();
408 //       i_this.setLists(this, _p_other, false);
409 //       if(_p_other && !(*_p_other)->empty())
410 //       {
411 //         reverse_iterator i_other = (*_p_other)->rbegin();
412 //         i_other.setLists(this, _p_other, true);
413 //         if(vlist::empty() || i_other->first > i_this->first)
414 //           return i_other;
415 //       }
416 //       return i_this;
417 //     }
418 //
419 //     const_reverse_iterator rbegin() const noexcept
420 //     {
421 //       const_reverse_iterator i_this = vlist::rbegin();
422 //       i_this.setLists(this, _p_other, false);
423 //       if(_p_other && !(*_p_other)->empty())
424 //       {
425 //         const MidiControllerList* mcl_other = *_p_other;
426 //         const_reverse_iterator i_other = mcl_other->rbegin();
427 //         i_other.setLists(this, _p_other, true);
428 //         if(vlist::empty() || i_other->first > i_this->first)
429 //           return i_other;
430 //       }
431 //       return i_this;
432 //     }
433 //
434 //     const_reverse_iterator crbegin() const noexcept
435 //     {
436 //       const_reverse_iterator i_this = vlist::crbegin();
437 //       i_this.setLists(this, _p_other, false);
438 //       if(_p_other && !(*_p_other)->empty())
439 //       {
440 //         const_reverse_iterator i_other = (*_p_other)->crbegin();
441 //         i_other.setLists(this, _p_other, true);
442 //         if(vlist::empty() || i_other->first > i_this->first)
443 //           return i_other;
444 //       }
445 //       return i_this;
446 //     }
447 //
448 //
449 //     // -------------------------------------------------------------------
450 //     // With these end iterators, we have a choice of either container.
451 //     // We could ask which container's end is more relevant by comparing
452 //     //  the decremented end iterators, or we could simply just take the
453 //     //  first container's. Which ever way we choose, it MUST be
454 //     //  consistent with the way our operator++/-- work.
455 //     // -------------------------------------------------------------------
456 //
457 //     iterator end() noexcept
458 //     {
459 //       iterator i_this = vlist::end();
460 //       i_this.setLists(this, _p_other, false);
461 // //       if(_p_other && !(*_p_other)->empty())
462 // //       {
463 // //         iterator i_other = (*_p_other)->end();
464 // //         i_other.setLists(this, _p_other, true);
465 // //         if(vlist::empty() || i_other->first > i_this->first)
466 // //           return i_other;
467 // //       }
468 //       return i_this;
469 //     }
470 //
471 //     const_iterator end() const noexcept
472 //     {
473 //       const_iterator i_this = vlist::end();
474 //       i_this.setLists(this, _p_other, false);
475 // //       if(_p_other && !(*_p_other)->empty())
476 // //       {
477 // //         const_iterator i_other = (*_p_other)->end();
478 // //         i_other.setLists(this, _p_other, true);
479 // //         if(vlist::empty() || i_other->first > i_this->first)
480 // //           return i_other;
481 // //       }
482 //       return i_this;
483 //     }
484 //
485 //     const_iterator cend() const noexcept
486 //     {
487 //       const_iterator i_this = vlist::cend();
488 //       i_this.setLists(this, _p_other, false);
489 // //       if(_p_other && !(*_p_other)->empty())
490 // //       {
491 // //         const_iterator i_other = (*_p_other)->cend();
492 // //         i_other.setLists(this, _p_other, true);
493 // //         if(vlist::empty() || i_other->first > i_this->first)
494 // //           return i_other;
495 // //       }
496 //       return i_this;
497 //     }
498 //
499 //     reverse_iterator rend() noexcept
500 //     {
501 //       reverse_iterator i_this = vlist::rend();
502 //       i_this.setLists(this, _p_other, false);
503 // //       if(_p_other && !(*_p_other)->empty())
504 // //       {
505 // //         reverse_iterator i_other = (*_p_other)->rend();
506 // //         i_other.setOtherList(_p_other, true);
507 // //         if(vlist::empty() || i_other->first < i_this->first)
508 // //           return i_other;
509 // //       }
510 //       return i_this;
511 //     }
512 //
513 //     const_reverse_iterator crend() const noexcept
514 //     {
515 //       const_reverse_iterator i_this = vlist::crend();
516 //       i_this.setLists(this, _p_other, false);
517 // //       if(_p_other && !(*_p_other)->empty())
518 // //       {
519 // //         const_reverse_iterator i_other = (*_p_other)->crend();
520 // //         i_other.setLists(this, _p_other, true);
521 // //         if(vlist::empty() || i_other->first < i_this->first)
522 // //           return i_other;
523 // //       }
524 //       return i_this;
525 //     }
526 //
527 //     bool empty() const noexcept
528 //     {
529 //       return vlist::empty() && (!_p_other || (*_p_other)->empty());
530 //     }
531 //
532 //     size_type size() const noexcept
533 //     {
534 //       return vlist::size() + (_p_other ? (*_p_other)->size() : 0);
535 //     }
536 //
537 //     iterator find(const int& key)
538 //     {
539 //       iterator i_this = vlist::find(key);
540 //       i_this.setLists(this, _p_other, false);
541 //       if(i_this == vlist::end() && _p_other)
542 //       {
543 //         iterator i_other = (*_p_other)->find(key);
544 //         i_other.setLists(this, _p_other, true);
545 //         if(i_other != (*_p_other)->end())
546 //           return i_other;
547 //       }
548 //       return i_this;
549 //     }
550 //
551 //     const_iterator find(const int& key) const
552 //     {
553 //       const_iterator i_this = vlist::find(key);
554 //       i_this.setLists(this, _p_other, false);
555 //       if(i_this == vlist::end() && _p_other)
556 //       {
557 //         const MidiControllerList* mcl_other = *_p_other;
558 //         const_iterator i_other = mcl_other->find(key);
559 //         i_other.setLists(this, _p_other, true);
560 //         if(i_other != mcl_other->end())
561 //           return i_other;
562 //       }
563 //       return i_this;
564 //     }
565 //
566 //     iterator lower_bound(const int& key)
567 //     {
568 //       iterator i_this = vlist::lower_bound(key);
569 //       i_this.setLists(this, _p_other, false);
570 //       if(i_this == vlist::end() && _p_other && !(*_p_other)->empty())
571 //       {
572 //         iterator i_other = (*_p_other)->lower_bound(key);
573 //         i_other.setLists(this, _p_other, true);
574 //         if(i_other != (*_p_other)->end() && (vlist::empty() || i_other->first < i_this->first))
575 //           return i_other;
576 //       }
577 //       return i_this;
578 //     }
579 //
580 //     const_iterator lower_bound(const int& key) const
581 //     {
582 //       const_iterator i_this = vlist::lower_bound(key);
583 //       i_this.setLists(this, _p_other, false);
584 //       if(i_this == vlist::end() && _p_other && !(*_p_other)->empty())
585 //       {
586 //         const MidiControllerList* mcl_other = *_p_other;
587 //         const_iterator i_other = mcl_other->lower_bound(key);
588 //         i_other.setLists(this, _p_other, true);
589 //         if(i_other != mcl_other->end() && (vlist::empty() || i_other->first < i_this->first))
590 //           return i_other;
591 //       }
592 //       return i_this;
593 //     }
594 //
595 //     iterator upper_bound(const int& key)
596 //     {
597 //       iterator i_this = vlist::upper_bound(key);
598 //       i_this.setLists(this, _p_other, false);
599 //       if(i_this == vlist::end() && _p_other && !(*_p_other)->empty())
600 //       {
601 //         iterator i_other = (*_p_other)->upper_bound(key);
602 //         i_other.setLists(this, _p_other, true);
603 //         if(i_other != (*_p_other)->end() && (vlist::empty() || i_other->first < i_this->first))
604 //           return i_other;
605 //       }
606 //       return i_this;
607 //     }
608 //
609 //     const_iterator upper_bound(const int& key) const
610 //     {
611 //       const_iterator i_this = vlist::upper_bound(key);
612 //       i_this.setLists(this, _p_other, false);
613 //       if(i_this == vlist::end() && _p_other && !(*_p_other)->empty())
614 //       {
615 //         const MidiControllerList* mcl_other = *_p_other;
616 //         const_iterator i_other = mcl_other->upper_bound(key);
617 //         i_other.setLists(this, _p_other, true);
618 //         if(i_other != mcl_other->end() && (vlist::empty() || i_other->first < i_this->first))
619 //           return i_other;
620 //       }
621 //       return i_this;
622 //     }
623 //
624 //
625 //
626 //
627 // //     // Returns an iterator that points to the inserted event.
628 // //     // Note that the pair's key part is IGNORED.
629 // //     // All information is gathered from the pair's value type T.
630 // //     // Returns end() if an error occurred.
631 // //     iCompoundMidiControllerList_t insert (const CompoundMidiControllerListInsertPair_t& v)
632 // //     {
633 // //       return add(v.second);
634 // //     }
635 // //
636 // //     // TODO:
637 // //     // template <class P> iMixedPosList insert (P&& v)  { return vlist::insert(v); }
638 // //     // iMixedPosList insert (ciMixedPosList pos, const T& v) { return vlist::insert(pos, v); }
639 // //     // template <class P> iMixedPosList insert (ciMixedPosList pos, P&& v) { return vlist::insert(pos, v); }
640 // //     // template <class InputIterator>
641 // //     // void insert (InputIterator first, InputIterator last) { return vlist::insert(first, last); }
642 // //     // void insert (std::initializer_list<T> il) { return vlist::insert(il); }
643 // //
644 // //     // Returns an iterator that points to the added event.
645 // //     // Returns end() if an error occurred.
646 // //     iMixedPosList_t add(const T& v)
647 // //     {
648 // //       const unsigned v_frame = v.frame();
649 // //       const unsigned v_tick = v.tick();
650 // //       ciMixedPosList_t pos = vlist::end();
651 // //       cMixedPosListRange_t r;
652 // //
653 // //       // If list type is ticks, compare frame. If list type is frames, compare tick.
654 // //       switch(type())
655 // //       {
656 // //         case Pos::TICKS:
657 // //           r = vlist::equal_range(v_tick);
658 // //           for(pos = r.first; pos != r.second; ++pos)
659 // //             if(v_frame < pos->second.frame())
660 // //               break;
661 // //           return vlist::insert(pos, MixedPosListInsertPair_t(v_tick, v));
662 // //         break;
663 // //
664 // //         case Pos::FRAMES:
665 // //           r = vlist::equal_range(v_frame);
666 // //           for(pos = r.first; pos != r.second; ++pos)
667 // //             if(v_tick < pos->second.tick())
668 // //               break;
669 // //           return vlist::insert(pos, MixedPosListInsertPair_t(v_frame, v));
670 // //         break;
671 // //       }
672 // //       return vlist::end();
673 // //     }
674 //
675 //
676 // };
677 
678 } // namespace MusECore
679 
680 #endif
681 
682