1 /* 2 * Hydrogen 3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net] 4 * 5 * http://www.hydrogen-music.org 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 */ 22 23 #ifndef EVENT_QUEUE_H 24 #define EVENT_QUEUE_H 25 26 #include <hydrogen/object.h> 27 #include <hydrogen/basics/note.h> 28 #include <cassert> 29 30 /** Maximum number of events to be stored in the 31 H2Core::EventQueue::__events_buffer.*/ 32 #define MAX_EVENTS 1024 33 34 namespace H2Core 35 { 36 37 /** Basic types of communication between the core part of Hydrogen and 38 its GUI.*/ 39 enum EventType { 40 /** Fallback event*/ 41 EVENT_NONE, 42 EVENT_STATE, 43 /** The current pattern changed during the processing of the 44 * AudioEngine with respect to the previous process cycle. 45 * 46 * It is handled by EventListener::patternChangedEvent(). 47 */ 48 EVENT_PATTERN_CHANGED, 49 EVENT_PATTERN_MODIFIED, 50 /** Another pattern was selected via MIDI or the GUI without 51 * affecting the audio transport (e.g in Song::PATTERN_MODE when 52 * Preferences::m_bPatternModePlaysSelected is set to true). While 53 * the selection in the former case already happens in the GUI, 54 * this event will be used to tell it the selection was successful 55 * and had been done. 56 * 57 * Handled by EventListener::selectedPatternChangedEvent(). 58 */ 59 EVENT_SELECTED_PATTERN_CHANGED, 60 EVENT_SELECTED_INSTRUMENT_CHANGED, 61 EVENT_PARAMETERS_INSTRUMENT_CHANGED, 62 EVENT_MIDI_ACTIVITY, 63 EVENT_XRUN, 64 EVENT_NOTEON, 65 EVENT_ERROR, 66 /** Event indicating the triggering of the 67 * #m_pMetronomeInstrument. 68 * 69 * In audioEngine_updateNoteQueue() the pushing of this Event is 70 * decoupled from the creation and queuing of the corresponding 71 * Note itself. 72 * 73 * In Director it triggers a change in the displayed number, 74 * color, tag, and triggers Director::update(). In case the 75 * provided value is 3, instead of performing the changes above, 76 * the Director loads the metadata a the current Song. 77 * 78 * The associated values do correspond to the following actions: 79 * - 0: Beat at the beginning of a Pattern in 80 * audioEngine_updateNoteQueue(). The corresponding Note will 81 * be created with a pitch of 3 and velocity of 1.0. 82 * Sets MetronomeWidget::m_state to 83 * MetronomeWidget::METRO_ON and triggers 84 * MetronomeWidget::updateWidget(). 85 * - 1: Beat in the remainder of a Pattern in 86 * audioEngine_updateNoteQueue(). The corresponding Note will 87 * be created with a pitch of 0 and velocity of 0.8. In 88 * addition, it will be also pushed by 89 * Hydrogen::setPatternPos() without creating a Note. 90 * Sets MetronomeWidget::m_state to 91 * MetronomeWidget::METRO_FIRST and triggers 92 * MetronomeWidget::updateWidget(). 93 * - 2: Signals MetronomeWidget to neither update nor setting 94 * MetronomeWidget::m_state. 95 * - 3: Tells the Director that a new Song was loaded and triggers 96 * its Director::update(). 97 * Sets MetronomeWidget::m_state to 98 * MetronomeWidget::METRO_ON and triggers 99 * MetronomeWidget::updateWidget(). 100 * 101 * Handled by EventListener::metronomeEvent(). 102 */ 103 EVENT_METRONOME, 104 EVENT_RECALCULATERUBBERBAND, 105 EVENT_PROGRESS, 106 EVENT_JACK_SESSION, 107 EVENT_PLAYLIST_LOADSONG, 108 EVENT_UNDO_REDO, 109 EVENT_SONG_MODIFIED, 110 EVENT_TEMPO_CHANGED, 111 /** 112 * Event triggering HydrogenApp::updateSongEvent() whenever the 113 * Song was changed outside of the GUI, e.g. by session management 114 * or and OSC command. 115 * 116 * If the value of the event is 117 * - 0 - Hydrogen::m_pNextSong will be loaded. 118 * - 1 - triggered whenever the #Song was saved via the core part 119 * (updated the title and status bar). 120 */ 121 EVENT_UPDATE_SONG, 122 /** 123 * Triggering HydrogenApp::quitEvent() and enables a shutdown of 124 * the entire application via the command line. 125 */ 126 EVENT_QUIT 127 }; 128 129 /** Basic building block for the communication between the core of 130 * Hydrogen and its GUI. The individual Events will be enlisted in 131 * the EventQueue singleton.*/ 132 class Event 133 { 134 public: 135 /** Specifies the context the event is create in and which 136 function should be triggered to handle it.*/ 137 EventType type; 138 /** Additional information to describe the actual context of 139 the engine.*/ 140 int value; 141 }; 142 143 /** Object handling the communication between the core of Hydrogen and 144 * its GUI. 145 * 146 * Whenever a specific condition is met or occasion happens within the 147 * core part of Hydrogen (its engine), an Event will be added to the 148 * EventQueue singleton. The GUI checks the content of this queue on a 149 * regular basis using HydrogenApp::onEventQueueTimer(). The actual 150 * frequency is set in the constructor HydrogenApp::HydrogenApp() to 151 * 20 times per second. Now, whenever an Event of a certain EventType 152 * is encountered, the corresponding function in the EventListener 153 * will be invoked to respond to the condition of the engine. For 154 * details about the mapping of EventTypes to functions please see the 155 * documentation of HydrogenApp::onEventQueueTimer().*/ 156 class EventQueue : public H2Core::Object 157 { 158 H2_OBJECT 159 public:/** 160 * If #__instance equals 0, a new EventQueue singleton will be 161 * created and stored in it. 162 * 163 * It is called in Hydrogen::create_instance(). 164 */ 165 static void create_instance(); 166 /** 167 * Returns a pointer to the current EventQueue singleton 168 * stored in #__instance. 169 */ get_instance()170 static EventQueue* get_instance() { assert(__instance); return __instance; } 171 ~EventQueue(); 172 173 /** 174 * Queues the next event into the EventQueue. 175 * 176 * The event itself will be constructed inside the function 177 * and will be two properties: an EventType @a type and a 178 * value @a nValue. Since the event written to the queue most 179 * recently is indexed with #__write_index, this variable is 180 * incremented once and its modulo with respect to #MAX_EVENTS 181 * is calculated to determine the position of insertion into 182 * #__events_buffer. 183 * 184 * The modulo operation is necessary because #__write_index 185 * will be only incremented and does not respect the actual 186 * length of #__events_buffer itself. 187 * 188 * \param type Type of the event, which will be queued. 189 * \param nValue Value specifying the content of the new event. 190 */ 191 void push_event( const EventType type, const int nValue ); 192 /** 193 * Reads out the next event of the EventQueue. 194 * 195 * Since the event read out most recently is indexed with 196 * #__read_index, this variable is incremented once and its 197 * modulo with respect to #MAX_EVENTS is calculated to 198 * determine the event returned from #__events_buffer. 199 * 200 * The modulo operation is necessary because #__read_index 201 * will be only incremented and does not respect the actual 202 * length of #__events_buffer itself. 203 * 204 * \return Next event in line. 205 */ 206 Event pop_event(); 207 208 struct AddMidiNoteVector { 209 int m_column; //position 210 int m_row; //instrument row 211 int m_pattern; // pattern number 212 int m_length; 213 float f_velocity; 214 float f_pan_L; 215 float f_pan_R; 216 Note::Key nk_noteKeyVal; 217 Note::Octave no_octaveKeyVal; 218 bool b_isMidi; 219 bool b_isInstrumentMode; 220 bool b_noteExist; 221 }; 222 std::vector<AddMidiNoteVector> m_addMidiNoteVector; 223 224 private: 225 /** 226 * Constructor of the EventQueue class. 227 * 228 * It fills all #MAX_EVENTS slots of the #__events_buffer with 229 * #H2Core::EVENT_NONE and assigns itself to #__instance. Called by 230 * create_instance(). 231 */ 232 EventQueue(); 233 /** 234 * Object holding the current EventQueue singleton. It is 235 * initialized with nullptr, set in EventQueue(), and 236 * accessed via get_instance(). 237 */ 238 static EventQueue *__instance; 239 240 /** 241 * Continuously growing number indexing the event, which has 242 * been read from the EventQueue most recently. 243 * 244 * It is incremented with each call to pop_event(). 245 */ 246 unsigned int __read_index; 247 /** 248 * Continuously growing number indexing the event, which has 249 * been written to the EventQueue most recently. 250 * 251 * It is incremented with each call to push_event(). 252 */ 253 unsigned int __write_index; 254 /** 255 * Array of all events contained in the EventQueue. 256 * 257 * Its length is set to #MAX_EVENTS and it gets initialized 258 * with #H2Core::EVENT_NONE in EventQueue(). 259 */ 260 Event __events_buffer[ MAX_EVENTS ]; 261 }; 262 263 }; 264 265 #endif 266