1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: song.h,v 1.35.2.25 2009/12/15 03:39:58 terminator356 Exp $
5 //
6 //  (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU General Public License
10 //  as published by the Free Software Foundation; version 2 of
11 //  the License, or (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 //=========================================================
23 
24 #ifndef __SONG_H__
25 #define __SONG_H__
26 
27 #include <QObject>
28 #include <QStringList>
29 #include <QFont>
30 
31 #include <map>
32 #include <set>
33 #include <list>
34 
35 #include "type_defs.h"
36 #include "pos.h"
37 #include "globaldefs.h"
38 #include "tempo.h"
39 #include "sig.h"
40 #include "synth.h"
41 #include "operations.h"
42 #include "lock_free_buffer.h"
43 #include "mpevent.h"
44 #include "wave.h"
45 
46 
47 #define IPC_EVENT_FIFO_SIZE ( std::min( std::max(size_t(256), size_t(MusEGlobal::segmentSize * 16)),  size_t(16384)) )
48 
49 #include "time_stretch.h"
50 #include "audio_convert/audio_converter_settings_group.h"
51 
52 
53 // Forward declarations:
54 class QAction;
55 class QMenu;
56 
57 namespace MusECore {
58 
59 class Event;
60 class Xml;
61 class Track;
62 class Part;
63 class PartList;
64 class EventList;
65 class MarkerList;
66 class Marker;
67 class Route;
68 struct AudioMsg;
69 class MidiPart;
70 class Undo;
71 struct UndoOp;
72 class UndoList;
73 
74 #define REC_NOTE_FIFO_SIZE    16
75 
76 //---------------------------------------------------------
77 //    Song
78 //---------------------------------------------------------
79 
80 class Song : public QObject {
81       Q_OBJECT
82 
83    public:
84       enum POSTYPE    { CPOS = 0, LPOS, RPOS };
85       enum FollowMode { NO, JUMP, CONTINUOUS };
86       enum            { REC_OVERDUP, REC_REPLACE };
87       enum            { CYCLE_NORMAL, CYCLE_MIX, CYCLE_REPLACE };
88       enum { MARKER_CUR };
89       enum OperationType {
90         // Execute the operation only, the operation is not un-doable. No song update.
91         OperationExecute,
92         // Execute the operation only, the operation is not un-doable. Song is updated.
93         OperationExecuteUpdate,
94         // Execute the operation, the operation is un-doable,
95         //  and do not 'start' and 'end' the undo mode. No song update.
96         OperationUndoable,
97         // Execute the operation, the operation is un-doable,
98         //  and do not 'start' and 'end' the undo mode. Song is updated.
99         OperationUndoableUpdate,
100         // Execute the operation, the operation is un-doable,
101         //  and 'start' and 'end' the undo mode. Song is updated.
102         OperationUndoMode
103       };
104 
105    private:
106       // fifo for note-on events
107       //    - this events are read by the heart beat interrupt
108       //    - used for single step recording in midi editors
109 
110       int recNoteFifo[REC_NOTE_FIFO_SIZE];
111       volatile int noteFifoSize;
112       int noteFifoWindex;
113       int noteFifoRindex;
114 
115       volatile char rcCC = -1; // CC remote control
116 
117       TempoFifo _tempoFifo; // External tempo changes, processed in heartbeat.
118 
119       MusECore::SongChangedStruct_t updateFlags;
120 
121       TrackList _tracks;      // tracklist as seen by arranger
122       MidiTrackList  _midis;
123       WaveTrackList _waves;
124       InputList _inputs;      // audio input ports
125       OutputList _outputs;    // audio output ports
126       GroupList _groups;      // mixer groups
127       AuxList _auxs;          // aux sends
128       SynthIList _synthIs;
129 
130       UndoList* undoList;
131       UndoList* redoList;
132       // New items created in GUI thread awaiting addition in audio thread.
133       PendingOperationList pendingOperations;
134 
135       Pos pos[3];
136       Pos _vcpos;               // virtual CPOS (locate in progress)
137       MarkerList* _markerList;
138 
139       float _fCpuLoad;
140       float _fDspLoad;
141       long _xRunsCount;
142 
143       // Receives events from any threads. For now, specifically for creating new
144       //  controllers in the gui thread and adding them safely to the controller lists.
145       LockFreeMPSCRingBuffer<MidiPlayEvent> *_ipcInEventBuffers;
146       LockFreeMPSCRingBuffer<MidiPlayEvent> *_ipcOutEventBuffers;
147 
148       bool loopFlag;
149       bool punchinFlag;
150       bool punchoutFlag;
151       bool recordFlag;
152       bool soloFlag;
153       int _recMode;
154       int _cycleMode;
155       Pos _startPlayPosition;
156       bool _click;
157       bool _quantize;
158       unsigned _len;         // song len in ticks
159       FollowMode _follow;
160       int _globalPitchShift;
161       void readMarker(Xml&);
162 
163       QString songInfoStr;  // contains user supplied song information, stored in song file.
164       bool showSongInfo;
165 
166       // Private: Update the audio device's real transport position after a tempo or master change for ex.
167       void updateTransportPos(const SongChangedStruct_t& flags);
168 
169       // These are called from non-RT thread operations execution stage 1.
170       void insertTrackOperation(Track* track, int idx, PendingOperationList& ops);
171       bool adjustMarkerListOperation(MarkerList* markerlist, unsigned int startPos, int diff, PendingOperationList& ops);
172       void removeTrackOperation(Track* track, PendingOperationList& ops);
173       bool addEventOperation(const Event&, Part*, bool do_port_ctrls = true, bool do_clone_port_ctrls = true);
174       // Special: Returns the real actual event to be deleted found in the event lists.
175       // This way even a modified event can be passed in, and as long as
176       //  the ID AND position values match it will find and return the ORIGINAL event.
177       // Useful for example for passing a pre-modified event to a DeleteEvent or ModyfyEvent operation
178       //  in the Undo system, and it will automatically replace the Undo item's event with
179       //  the real one returned here. (Otherwise when the user hits 'undo' it would restore
180       //  that modified passed-in event sitting in the Undo item. That's not the right event!)
181       Event changeEventOperation(const Event& oldEvent, const Event& newEvent,
182                                 Part*, bool do_port_ctrls = true, bool do_clone_port_ctrls = true);
183       Event deleteEventOperation(const Event&, Part*, bool do_port_ctrls = true, bool do_clone_port_ctrls = true);
184 
185       void checkSongSampleRate();
186 
187       void normalizePart(MusECore::Part *part);
188 
189       // Fills operations if given, otherwise creates and executes its own operations list.
190       void processTrackAutomationEvents(AudioTrack *atrack, Undo* operations = 0);
191 
192    public:
193       Song(const char* name = 0);
194       ~Song();
195 
196       /** It is not allowed nor checked(!) to AddPart a clone, and
197        *  to AddEvent/DeleteEvent/ModifyEvent/SelectEvent events which
198        *  would need to be replicated to the newly added clone part!
199        */
200       // group may be changed! prepareOperationGroup is called on group!
201       // Sender can be set to the caller object and used by it
202       //  to ignore self-generated songChanged signals.
203       // The songChanged structure will contain this pointer.
204       bool applyOperationGroup(Undo& group, OperationType type = OperationUndoMode, void* sender = 0);
205       bool applyOperation(const UndoOp& op, OperationType type = OperationUndoMode, void* sender = 0);
206 
207       /** this sends emits a signal to each MidiEditor or whoever is interested.
208        *  For each part which is 1) opened in this MidiEditor and 2) which is
209        *  a key in this map, the Editors shall no more edit this part, but instead
210        *  all parts in the_map[old_part] (which is a std::set<Part*>)
211        */
212       void informAboutNewParts(const std::map< const Part*, std::set<const Part*> >&);
213       /** this sends emits a signal to each MidiEditor or whoever is interested.
214        *  For each part which is 1) opened in this MidiEditor and 2) which is
215        *  a key in this map, the Editors shall no more edit this part, but instead
216        *  all parts in the_map[old_part] (which is a std::set<Part*>)
217        *  this is a special case of the general function, which only replaces one part
218        *  by up to nine different.
219        */
220       void informAboutNewParts(const Part* orig, const Part* p1, const Part* p2=NULL, const Part* p3=NULL, const Part* p4=NULL, const Part* p5=NULL, const Part* p6=NULL, const Part* p7=NULL, const Part* p8=NULL, const Part* p9=NULL);
221 
222       void putEvent(int pv);
223       void putEventCC(char cc);
224       void endMsgCmd();
225       void processMsg(AudioMsg* msg);
226 
setFollow(FollowMode m)227       void setFollow(FollowMode m)     { _follow = m; }
follow()228       FollowMode follow() const        { return _follow; }
229 
230       bool dirty;
231       WaveTrack* bounceTrack;
232       AudioOutput* bounceOutput;
233       void updatePos();
234 
235       void read(Xml&, bool isTemplate=false);
236       void write(int, Xml&) const;
237 //      void writeFont(int level, Xml& xml, const char* name,
238 //         const QFont& font) const;
239 //      QFont readFont(Xml& xml, const char* name);
240       // After a song file is successfully loaded with read(), some items which
241       //  reference other items in the file need to be resolved. (Mixer strip configs etc.)
242       void resolveSongfileReferences();
243 
getSongInfo()244       QString getSongInfo() { return songInfoStr; }
setSongInfo(QString info,bool show)245       void setSongInfo(QString info, bool show) { songInfoStr = info; showSongInfo = show; }
showSongInfoOnStartup()246       bool showSongInfoOnStartup() { return showSongInfo; }
247 
248       // If clear_all is false, it will not touch things like midi ports.
249       void clear(bool signal, bool clear_all = true);
250       void cleanupForQuit();
251 
globalPitchShift()252       int globalPitchShift() const      { return _globalPitchShift; }
setGlobalPitchShift(int val)253       void setGlobalPitchShift(int val) { _globalPitchShift = val; }
254 
255       // REMOVE Tim. samplerate. Added. TODO
256 #if 0
257       // Set the project's sample rate. This can be different than the current actual sample rate.
258       void setProjectSampleRate(int rate);
259       // Ratio of the project's sample rate to the current audio sample rate.
260       double projectSampleRateRatio() const;
261       // Whether the project's sample rate ratio is exactly 1.
262       bool projectSampleRateDiffers() const;
263       // This scales the sample rate, by scaling the frame values of all objects or properties that use or store
264       //  a value in 'frames', such as wave parts/events position and length, and audio automation graphs.
265       // It does NOT resample audio files, that is another function.
266       // Caution: Slight rounding errors can degrade timing accuracy, especially if repeated scalings are done.
267       void convertProjectSampleRate(int newRate);
268 #endif
269 
270       //-----------------------------------------
271       //   Marker
272       //-----------------------------------------
273 
marker()274       MarkerList* marker() const { return _markerList; }
275       // For wholesale swapping of a new list. Takes ownership of the given list.
setMarkerList(MarkerList * ml)276       void setMarkerList(MarkerList* ml) { _markerList = ml; }
277       void addMarker(const QString& s, unsigned t, bool lck);
278       void addMarker(const QString& s, const Pos& p);
279       iMarker getMarkerAt(unsigned t);
280       void removeMarker(const Marker&);
281       void setMarkerName(const Marker&, const QString&);
282       void setMarkerPos(const Marker&, const Pos& pos);
283       void setMarkerLock(const Marker&, bool);
284 
285       //-----------------------------------------
286       //   transport
287       //-----------------------------------------
288 
289       void setPos(POSTYPE posType, const Pos&, bool sig = true, bool isSeek = true,
290          bool adjustScrollbar = false, bool force = false);
cPos()291       const Pos& cPos() const       { return pos[0]; }
lPos()292       const Pos& lPos() const       { return pos[1]; }
rPos()293       const Pos& rPos() const       { return pos[2]; }
cpos()294       unsigned cpos() const         { return pos[0].tick(); }
vcpos()295       unsigned vcpos() const        { return _vcpos.tick(); }
vcPos()296       const Pos& vcPos() const      { return _vcpos; }
lpos()297       unsigned lpos() const         { return pos[1].tick(); }
rpos()298       unsigned rpos() const         { return pos[2].tick(); }
299 
loop()300       bool loop() const             { return loopFlag; }
record()301       bool record() const           { return recordFlag; }
punchin()302       bool punchin() const          { return punchinFlag; }
punchout()303       bool punchout() const         { return punchoutFlag; }
304       void setRecMode(int val);
recMode()305       int  recMode() const          { return _recMode; }
306       void setCycleMode(int val);
cycleMode()307       int cycleMode() const         { return _cycleMode; }
click()308       bool click() const            { return _click; }
quantize()309       bool quantize() const         { return _quantize; }
310       void setStopPlay(bool);
311       // Fills operations if given, otherwise creates and executes its own operations list.
312       void stopRolling(Undo* operations = 0);
313       void abortRolling();
314 
cpuLoad()315       float cpuLoad() const { return _fCpuLoad; }
dspLoad()316       float dspLoad() const { return _fDspLoad; }
xRunsCount()317       long xRunsCount() const { return _xRunsCount; }
318 
319       //-----------------------------------------
320       //    access tempomap/MusEGlobal::sigmap  (Mastertrack)
321       //-----------------------------------------
322 
len()323       unsigned len() const { return _len; }
324       void setLen(unsigned l, bool do_update = true);     // set songlen in ticks
325       int roundUpBar(int tick) const;
326       int roundUpBeat(int tick) const;
327       int roundDownBar(int tick) const;
328       void initLen();
329 
330       //-----------------------------------------
331       //   event manipulations
332       //-----------------------------------------
333 
334       void cmdAddRecordedWave(WaveTrack* track, Pos s, Pos e, Undo& operations);
335       void cmdAddRecordedEvents(MidiTrack*, const EventList&, unsigned, Undo& operations);
336 
337       // May be called from GUI or audio thread. Also selects events in clone parts. Safe for now because audio/midi processing doesn't
338       //  depend on it, and all calls to part altering functions from GUI are synchronized with (wait for) audio thread.
339       void selectEvent(Event&, Part*, bool select);
340       void selectAllEvents(Part*, bool select); // See selectEvent().
341 
342       void cmdChangeWave(const Event& original, const QString& tmpfile, unsigned sx, unsigned ex);
343       void remapPortDrumCtrlEvents(int mapidx, int newnote, int newchan, int newport); // called from GUI thread
344       // Adds or removes midi event controller cache values.
345       // Called from GUI thread
346       // add true: add events. false: remove events
347       // drum_tracks: Include drum tracks. midi_tracks: Include midi tracks.
348       // drum_ctls: Do drum (per-note) controller events. non_drum_ctls: Do non-drum controller events.
349       void changeMidiCtrlCacheEvents(
350         bool add, bool drum_tracks = true, bool midi_tracks = true, bool drum_ctls = true, bool non_drum_ctls = true);
351 
addExternalTempo(const TempoRecEvent & e)352       void addExternalTempo(const TempoRecEvent& e) { _tempoFifo.put(e); }
353 
354       //--------------------------------------------
355       //   Time-stretch / samplerate manipulations
356       //--------------------------------------------
357 
358       void stretchModifyOperation(
359          StretchList* stretch_list, StretchListItem::StretchEventType type, double value,
360          PendingOperationList& ops) const;
361       void stretchListAddOperation(
362         StretchList* stretch_list, StretchListItem::StretchEventType type, MuseFrame_t frame,
363         double value, PendingOperationList& ops) const;
364       void stretchListDelOperation(
365         StretchList* stretch_list, int types, MuseFrame_t frame, PendingOperationList& ops) const;
366       void stretchListModifyOperation(
367         StretchList* stretch_list, StretchListItem::StretchEventType type, MuseFrame_t frame,
368         double value, PendingOperationList& ops) const;
369 
370       void setAudioConvertersOfflineOperation(
371         bool isOffline
372         );
373 
374       void modifyAudioConverterSettingsOperation(
375         SndFileR sndfile,
376         AudioConverterSettingsGroup* settings,
377         AudioConverterSettingsGroup* defaultSettings,
378         bool isLocalSettings,
379         PendingOperationList& ops
380         ) const;
381 
382       void modifyAudioConverterOperation(
383         SndFileR sndfile,
384         PendingOperationList& ops,
385         bool doResample,
386         bool doStretch
387         ) const;
388 
389       void modifyStretchListOperation(
390         SndFileR sndfile, int type, double value, PendingOperationList& ops) const;
391       void addAtStretchListOperation(
392         SndFileR sndfile, int type, MuseFrame_t frame, double value, PendingOperationList& ops) const;
393       void delAtStretchListOperation(
394         SndFileR sndfile, int types, MuseFrame_t frame, PendingOperationList& ops) const;
395       void modifyAtStretchListOperation(
396         SndFileR sndfile, int type, MuseFrame_t frame, double value, PendingOperationList& ops) const;
397       void modifyDefaultAudioConverterSettingsOperation(
398         AudioConverterSettingsGroup* settings, PendingOperationList& ops);
399 
400       //-----------------------------------------
401       //   part manipulations
402       //-----------------------------------------
403 
404       void addPart(Part* part);
405       void removePart(Part* part);
406       void changePart(Part*, Part*);
407 
408       void normalizeWaveParts(Part *partCursor = NULL);
409 
410       //-----------------------------------------
411       //   track manipulations
412       //-----------------------------------------
413 
tracks()414       TrackList* tracks()       { return &_tracks;  }
midis()415       MidiTrackList* midis()    { return &_midis;   }
waves()416       WaveTrackList* waves()    { return &_waves;   }
inputs()417       InputList* inputs()       { return &_inputs;  }
outputs()418       OutputList* outputs()     { return &_outputs; }
groups()419       GroupList* groups()       { return &_groups;  }
auxs()420       AuxList* auxs()           { return &_auxs;    }
syntis()421       SynthIList* syntis()      { return &_synthIs; }
422 
423       Track* findTrack(const Part* part) const;
424       Track* findTrack(const QString& name) const;
trackExists(Track * t)425       bool trackExists(Track* t) const { return _tracks.find(t) != _tracks.cend(); }
426 
427       void setRecordFlag(Track*, bool val, Undo* operations = 0);
428       // This is a non- realtime safe operation mainly used when loading files, while the engine is paused or idle.
429       void insertTrack0(Track*, int idx);
430 
431       // The currently selected track (in a multi-selection the last one selected), or null.
selectedTrack()432       Track* selectedTrack() const { return _tracks.currentSelection(); }
433       // Total number of selected tracks.
countSelectedTracks()434       int countSelectedTracks() const { return _tracks.countSelected(); }
435       // Selects or deselects all tracks.
selectAllTracks(bool select)436       void selectAllTracks(bool select)
437       {
438         _tracks.selectAll(select);
439         if(!select) // Not essential, but if unselecting ALL tracks, clear the static counter.
440           Track::clearSelectionOrderCounter();
441       }
442 
443       void readRoute(Xml& xml);
444       void recordEvent(MidiTrack*, Event&);
445       // Enable all track and plugin controllers, and synth controllers if applicable, which are NOT in AUTO_WRITE mode.
446       void reenableTouchedControllers();
447       void clearRecAutomation(bool clearList);
448       // Fills operations if given, otherwise creates and executes its own operations list.
449       void processAutomationEvents(Undo* operations = 0);
450       void processMasterRec();
451       int execAutomationCtlPopup(AudioTrack*, const QPoint&, int);
452       int execMidiAutomationCtlPopup(MidiTrack*, MidiPart*, const QPoint&, int);
453       bool connectJackRoutes(const MusECore::Route& src, const MusECore::Route& dst, bool disconnect = false);
454       void connectAudioPorts();
455       void connectMidiPorts();
connectAllPorts()456       void connectAllPorts() { connectAudioPorts(); connectMidiPorts(); }
457       void updateSoloStates();
458       // Put an event into the IPC event ring buffer for the gui thread to process. Returns true on success.
459       // NOTE: Although the ring buffer is multi-writer, call this from audio thread only for now, unless
460       //  you know what you are doing because the thread needs to ask whether the controller exists before
461       //  calling, and that may not be safe from threads other than gui or audio.
462       bool putIpcInEvent(const MidiPlayEvent& ev);
463       // Put an event into the IPC event ring buffer for the audio thread to process.
464       // Called by gui thread only. Returns true on success.
465       bool putIpcOutEvent(const MidiPlayEvent& ev);
466       // Process any special IPC audio thread - to - gui thread messages.
467       // Called by gui thread only. Returns true on success.
468       bool processIpcInEventBuffers();
469       // Process any special gui thread - to - IPC audio thread messages.
470       // Called by audio thread only. Returns true on success.
471       bool processIpcOutEventBuffers();
472 
473       //-----------------------------------------
474       //   undo, redo, operation groups
475       //-----------------------------------------
476 
477       // Sender can be set to the caller object and used by it
478       //  to ignore self-generated songChanged signals.
479       // The songChanged structure will contain this pointer.
480       void startUndo(void* sender = 0);
481       void endUndo(MusECore::SongChangedStruct_t);
482 
483       void executeOperationGroup1(Undo& operations);
484       void executeOperationGroup2(Undo& operations);
485       void executeOperationGroup3(Undo& operations);
486       void revertOperationGroup1(Undo& operations);
487       void revertOperationGroup2(Undo& operations);
488       void revertOperationGroup3(Undo& operations);
489 
490       void addUndo(UndoOp i);
491       void setUndoRedoText();
492 
493       //-----------------------------------------
494       //   Configuration
495       //-----------------------------------------
496 
497       SynthI* createSynthI(const QString& sclass, const QString& uri, const QString& label = QString(),
498                            Synth::Type type = Synth::SYNTH_TYPE_END, Track* insertAt = 0);
499 
500       //-----------------------------------------
501       //   Debug
502       //-----------------------------------------
503 
504       void dumpMaster();
addUpdateFlags(MusECore::SongChangedStruct_t f)505       void addUpdateFlags(MusECore::SongChangedStruct_t f)  { updateFlags |= f; }
506 
507       //-----------------------------------------
508       //   Python bridge related
509       //-----------------------------------------
510 #ifdef PYTHON_SUPPORT
511       virtual bool event (QEvent* e );
512 #endif
513 
514    public slots:
515       void seekTo(int tick);
516       // use allowRecursion with care! this could lock up muse if you
517       //  aren't sure that your recursion will be finite!
518       void update(SongChangedStruct_t flags = SongChangedStruct_t(SC_EVERYTHING),
519                   bool allowRecursion=false);
520       void beat();
521 
522       void undo();
523       void redo();
524 
525       void setTempo(int t);
526       void setSig(int a, int b);
527       void setSig(const MusECore::TimeSignature&);
setTempo(double tempo)528       void setTempo(double tempo)  { setTempo(int(60000000.0/tempo)); }
529 
530       void setMasterFlag(bool flag);
getLoop()531       bool getLoop() { return loopFlag; }
532       void setLoop(bool f);
533       void setRecord(bool f, bool autoRecEnable = true);
534       void clearTrackRec();
535       void setPlay(bool f);
536       void setStop(bool);
537       void forward();
538       void rewindStart();
539       void rewind();
540       void setPunchin(bool f);
541       void setPunchout(bool f);
542       void setClick(bool val);
543       void setQuantize(bool val);
544       void panic();
545       void seqSignal(int fd);
546       // Creates a track but does not add it to the track list, the caller must do that.
547       // The track name is not set and must be set by the caller.
548       // If setDefaults is true, adds default in/out routes/channels to the track.
549       Track* createTrack(Track::TrackType type, bool setDefaults = true);
550       Track* addTrack(Track::TrackType type, Track* insertAt = 0);
551       Track* addNewTrack(QAction* action, Track* insertAt = 0);
552       void duplicateTracks(Track* t = nullptr);
setDirty()553       void setDirty() { emit sigDirty(); }
554 
555       /* restarts recording from last start position
556        * if discard is true (default) then
557        * recording will start on existing tracks,
558        * else new copies of armed tracks will be created
559        * and current armed tracks will be muted and unarmed
560        * Called from gui thread only. */
561       void restartRecording(bool discard = true);
562 
563    signals:
564       void songChanged(MusECore::SongChangedStruct_t);
565       void posChanged(int, unsigned, bool);
566       void posChanged(int, const MusECore::Pos, bool);
567       void loopChanged(bool);
568       void recordChanged(bool);
569       void playChanged(bool);
570       void punchinChanged(bool);
571       void punchoutChanged(bool);
572       void clickChanged(bool);
573       void quantizeChanged(bool);
574       void markerChanged(int);
575       void midiNote(int pitch, int velo);
576       void controllerChanged(MusECore::Track*, int);
577       void newPartsCreated(const std::map< const MusECore::Part*, std::set<const MusECore::Part*> >&);
578       void sigDirty();
579       void recModeChanged(int);
580       void cycleModeChanged(int);
581       };
582 
583 } // namespace MusECore
584 
585 namespace MusEGlobal {
586 extern MusECore::Song* song;
587 }
588 
589 #endif
590 
591