00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "MusicProcess.h"
00021 #include "GameData.h"
00022 #include "MusicFlex.h"
00023 #include "MidiDriver.h"
00024 #include "XMidiFile.h"
00025 #include "XMidiEventList.h"
00026 #include "AudioMixer.h"
00027
00028 #include "ObjectManager.h"
00029 #include "getObject.h"
00030 #include "MainActor.h"
00031
00032 #include "IDataSource.h"
00033 #include "ODataSource.h"
00034
00035
00036 DEFINE_RUNTIME_CLASSTYPE_CODE(MusicProcess,Process);
00037
00038 MusicProcess * MusicProcess::the_music_process = 0;
00039
00040 MusicProcess::MusicProcess()
00041 : current_track(0)
00042 {
00043 std::memset(song_branches, -1, 128*sizeof(int));
00044 }
00045
00046 MusicProcess::MusicProcess(MidiDriver *drv) :
00047 driver(drv), state(MUSIC_NORMAL), current_track(0),
00048 wanted_track(0), last_request(0), queued_track(0)
00049 {
00050 std::memset(song_branches, -1, 128*sizeof(int));
00051
00052 the_music_process = this;
00053 flags |= PROC_RUNPAUSED;
00054 type = 1;
00055 }
00056
00057 MusicProcess::~MusicProcess()
00058 {
00059 the_music_process = 0;
00060 }
00061
00062 void MusicProcess::playMusic(int track)
00063 {
00064 last_request = track;
00065
00066 ObjectManager* om = ObjectManager::get_instance();
00067 if (om && getMainActor()) {
00068 MainActor* av = getMainActor();
00069 if (av->isInCombat() || (av->getActorFlags() & Actor::ACT_COMBATRUN))
00070 {
00071
00072 return;
00073 }
00074 }
00075
00076 if (queued_track) {
00077 queued_track = track;
00078 return;
00079 }
00080
00081 playMusic_internal(track);
00082 }
00083
00084 void MusicProcess::playCombatMusic(int track)
00085 {
00086 playMusic_internal(track);
00087 }
00088
00089 void MusicProcess::queueMusic(int track)
00090 {
00091 if (wanted_track != track) {
00092 queued_track = track;
00093 }
00094 }
00095
00096 void MusicProcess::unqueueMusic()
00097 {
00098 queued_track = 0;
00099 }
00100
00101 void MusicProcess::restoreMusic()
00102 {
00103 queued_track = 0;
00104 playMusic_internal(last_request);
00105 }
00106
00107
00108
00109 void MusicProcess::playMusic_internal(int track)
00110 {
00111 if (track < 0 || track > 128)
00112 {
00113 playMusic_internal(0);
00114 return;
00115 }
00116
00117
00118 if (driver && !driver->isSequencePlaying(0))
00119 wanted_track = current_track = 0;
00120
00121
00122 if (current_track == track && state == MUSIC_NORMAL)
00123 {
00124 return;
00125 }
00126 else if (current_track == 0 || state != MUSIC_NORMAL || !driver)
00127 {
00128 wanted_track = track;
00129 state = MUSIC_PLAY_WANTED;
00130 }
00131
00132 else
00133 {
00134 const MusicFlex::SongInfo *info = GameData::get_instance()->getMusic()->getSongInfo(current_track);
00135
00136 uint32 measure = driver->getSequenceCallbackData(0);
00137
00138
00139 if (!info || (measure >= (uint32)info->num_measures) ||
00140 !info->transitions[track] || !info->transitions[track][measure])
00141 {
00142 current_track = 0;
00143 if (track == 0)
00144 {
00145 wanted_track = 0;
00146 state = MUSIC_PLAY_WANTED;
00147 }
00148 else
00149 {
00150 playMusic_internal(track);
00151 }
00152 return;
00153 }
00154
00155
00156 int trans = info->transitions[track][measure];
00157 bool speed_hack = false;
00158
00159 if (trans < 0)
00160 {
00161 trans = (-trans)-1;
00162 speed_hack = true;
00163 }
00164 else
00165 {
00166 driver->finishSequence(0);
00167 trans = trans-1;
00168 }
00169
00170
00171 int xmidi_index = driver->isFMSynth()?260:258;
00172 XMidiFile *xmidi = GameData::get_instance()->getMusic()->getXMidi(xmidi_index);
00173 XMidiEventList *list;
00174
00175 if (xmidi) list = xmidi->GetEventList(trans);
00176 else list = 0;
00177
00178 if (list)
00179 {
00180 driver->startSequence(1, list, false, 255, song_branches[track]);
00181 if (speed_hack) driver->setSequenceSpeed(1,200);
00182 }
00183 else driver->finishSequence(1);
00184 wanted_track = track;
00185
00186 state = MUSIC_TRANSITION;
00187 }
00188 }
00189
00190 bool MusicProcess::run(const uint32)
00191 {
00192 switch (state)
00193 {
00194 case MUSIC_NORMAL:
00195 if (driver && !driver->isSequencePlaying(0) && queued_track) {
00196 wanted_track = queued_track;
00197 state = MUSIC_PLAY_WANTED;
00198 queued_track = 0;
00199 }
00200
00201 break;
00202
00203 case MUSIC_TRANSITION:
00204 if (!driver)
00205 {
00206 state = MUSIC_PLAY_WANTED;
00207 }
00208 else if (!driver->isSequencePlaying(1))
00209 {
00210 state = MUSIC_PLAY_WANTED;
00211 driver->pauseSequence(0);
00212 driver->finishSequence(0);
00213 }
00214 break;
00215
00216 case MUSIC_PLAY_WANTED:
00217 {
00218 if (driver)
00219 {
00220 driver->finishSequence(0);
00221 driver->finishSequence(1);
00222 }
00223
00224 XMidiFile *xmidi = 0;
00225 if (wanted_track)
00226 {
00227 int xmidi_index = wanted_track;
00228 if (driver && driver->isFMSynth())
00229 xmidi_index += 128;
00230
00231 xmidi = GameData::get_instance()->getMusic()->getXMidi(xmidi_index);
00232 }
00233
00234 if (xmidi)
00235 {
00236 XMidiEventList *list = xmidi->GetEventList(0);
00237 if (song_branches[wanted_track] != -1)
00238 {
00239 XMidiEvent *event = list->findBranchEvent(song_branches[wanted_track]);
00240 if (!event) song_branches[wanted_track] = 0;
00241 }
00242
00243 if (driver) {
00244
00245 bool repeat = (queued_track == 0);
00246 driver->startSequence(0, list, repeat, 255, song_branches[wanted_track]);
00247 }
00248 current_track = wanted_track;
00249 song_branches[wanted_track]++;
00250 }
00251 else
00252 {
00253 current_track = wanted_track = 0;
00254 }
00255 state = MUSIC_NORMAL;
00256 }
00257 break;
00258 }
00259
00260 return false;
00261 }
00262
00263 void MusicProcess::saveData(ODataSource* ods)
00264 {
00265 Process::saveData(ods);
00266
00267 ods->write4(static_cast<uint32>(wanted_track));
00268 ods->write4(static_cast<uint32>(last_request));
00269 ods->write4(static_cast<uint32>(queued_track));
00270 }
00271
00272 bool MusicProcess::loadData(IDataSource* ids, uint32 version)
00273 {
00274 if (!Process::loadData(ids, version)) return false;
00275
00276 wanted_track = static_cast<sint32>(ids->read4());
00277
00278 if (version >= 4) {
00279 last_request = static_cast<sint32>(ids->read4());
00280 queued_track = static_cast<sint32>(ids->read4());
00281 } else {
00282 last_request = wanted_track;
00283 queued_track = 0;
00284 }
00285
00286 state = MUSIC_PLAY_WANTED;
00287
00288 the_music_process = this;
00289
00290 driver = Pentagram::AudioMixer::get_instance()->getMidiDriver();
00291
00292 return true;
00293 }
00294
00295 uint32 MusicProcess::I_musicStop(const uint8* ,
00296 unsigned int )
00297 {
00298 if (the_music_process) the_music_process->playMusic_internal(0);
00299 return 0;
00300 }
00301
00302 uint32 MusicProcess::I_playMusic(const uint8* args,
00303 unsigned int )
00304 {
00305 ARG_UINT8(song);
00306 if (the_music_process) the_music_process->playMusic(song&0x7F);
00307 return 0;
00308 }
00309
00310
00311 void MusicProcess::ConCmd_playMusic(const Console::ArgvType &argv)
00312 {
00313 if (the_music_process)
00314 {
00315 if (argv.size() != 2)
00316 {
00317 pout << "MusicProcess::playMusic (tracknum)" << std::endl;
00318 }
00319 else
00320 {
00321 pout << "Playing track " << argv[1] << std::endl;
00322 the_music_process->playMusic_internal(atoi(argv[1].c_str()));
00323 }
00324 }
00325 else
00326 {
00327 pout << "No Music Process" << std::endl;
00328 }
00329 }
00330
00331
00332
00333