1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 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; either version 2 10 * of 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 AUDIO_MIDIPLAYER_H 24 #define AUDIO_MIDIPLAYER_H 25 26 #include "common/scummsys.h" 27 #include "common/mutex.h" 28 #include "audio/mididrv.h" 29 30 class MidiParser; 31 32 namespace Audio { 33 34 /** 35 * Simple MIDI playback class. 36 * 37 * @note Currently incomplete, as it lacks play() methods. This is just a 38 * start of the real thing, which tries to include code replicated between 39 * several of our engines. 40 * 41 * Eventually, this should offer ways to start playback of SMF and XMIDI 42 * data (and possibly make it easy to add further playback methods), 43 * should be able to automatically instantiate _driver as needed, 44 * should perform memory management on the MidiParser object(s) being 45 * used, and possibly more. 46 * 47 * Also, pause/resume handling should be unified (we provide an implementation, 48 * but several subclasses use different ones). 49 * 50 * Also, care should be taken to ensure that mutex locking is done right. 51 * 52 * @todo Document origin of this class. It is based on code shared by 53 * several engines (e.g. DRACI says it copied it from MADE, which took 54 * it from SAGE). 55 */ 56 class MidiPlayer : public MidiDriver_BASE { 57 public: 58 MidiPlayer(); 59 ~MidiPlayer(); 60 61 // TODO: Implement ways to actually play stuff 62 //virtual void play(TODO); 63 64 // TODO: Document these 65 virtual void stop(); 66 virtual void pause(); 67 virtual void resume(); 68 69 /** 70 * Return whether there is currently any MIDI music playing. 71 * 72 * @todo There is a subtle difference between the semantics of this in 73 * various subclasses, related to paused music: Namely, should this 74 * function return true or false if a MIDI song is currently loaded, 75 * but paused? In the base implementation of pause/resume, "false" 76 * will be returned (that is, it is not possible to distinguish between 77 * nothing being played, and an active but paused MIDI tune). 78 * But in several subclasses (e.g. in HUGO), there is a separate _paused 79 * variable, which is used to pause playback, and for these, "true" 80 * will be returned. 81 * And in SAGA, isPlaying is overwritten to return the value 82 * of _parser->isPlaying() (which should amount to "true" in the 83 * described situation). 84 * We really should unify this and clearly define the desired 85 * semantics of this method. 86 */ isPlaying()87 bool isPlaying() const { return _isPlaying; } 88 89 /** 90 * Return the currently active master volume, in the range 0-255. 91 */ getVolume()92 int getVolume() const { return _masterVolume; } 93 94 /** 95 * Set the master volume to the specified value in the range 0-255. 96 * (values outside this range are automatically clipped). 97 * This may cause suitable MIDI events to be sent to active channels. 98 * 99 * @todo This method currently does not do anything if the new volume 100 * matches the old volume. But some engines always update the 101 * volume (Parallaction, Tinsel, Touche, ...). This is why 102 * this method is currently virtual. We really should figure 103 * which way to do it, and then make this the default, and make 104 * this method non-virtual again. 105 */ 106 virtual void setVolume(int volume); 107 108 /** 109 * Update the volume according to the ConfMan's 'music_volume' 110 * setting. also respects the 'mute' setting. 111 */ 112 void syncVolume(); 113 114 // TODO: Document this hasNativeMT32()115 bool hasNativeMT32() const { return _nativeMT32; } 116 117 // MidiDriver_BASE implementation 118 virtual void send(uint32 b); 119 virtual void metaEvent(byte type, byte *data, uint16 length); 120 121 protected: 122 /** 123 * This method is invoked by the default send() implementation, 124 * after suitably filtering the message b. 125 */ 126 virtual void sendToChannel(byte ch, uint32 b); 127 128 /** 129 * This method is invoked by metaEvent when an end-of-track 130 * event arrives. By default, this tells the parser 131 * to jump to the start (if looping is enabled) resp. 132 * invokes stope(): 133 * Overload this to customize behavior. 134 */ 135 virtual void endOfTrack(); 136 137 // TODO: Document this 138 virtual void onTimer(); 139 140 static void timerCallback(void *data); 141 142 void createDriver(int flags = MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); 143 144 protected: 145 enum { 146 /** 147 * The number of MIDI channels supported. 148 */ 149 kNumChannels = 16 150 }; 151 152 Common::Mutex _mutex; 153 MidiDriver *_driver; 154 155 /** 156 * A MidiParser instances, to be created by methods of a MidiPlayer 157 * subclass. 158 * @note The stop() method (and hence the destructor) invoke the 159 * unloadMusic() method of _parser and then delete it. 160 */ 161 MidiParser *_parser; 162 163 /** 164 * This is an (optional) pointer to a malloc'ed buffer containing 165 * MIDI data used by _parser. The stop() method (and hence the 166 * destructor) will free this if set. 167 * Subclasses of this class may use _midiData, but don't have to 168 */ 169 byte *_midiData; 170 171 MidiChannel *_channelsTable[kNumChannels]; 172 uint8 _channelsVolume[kNumChannels]; 173 174 bool _isLooping; 175 bool _isPlaying; 176 177 /** 178 * The master volume, in the range 0-255. 179 */ 180 int _masterVolume; // FIXME: byte or int ? 181 182 bool _nativeMT32; 183 }; 184 185 186 } // End of namespace Audio 187 188 #endif 189