MusicProcess.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2007 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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 // p_dynamic_cast stuff
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; // persistent
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                         // combat music active
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         // No current track if not playing
00118         if (driver && !driver->isSequencePlaying(0))
00119                 wanted_track = current_track = 0;
00120 
00121         // It's already playing and we are not transitioning
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         // We want to do a transition
00132         else
00133         {
00134                 const MusicFlex::SongInfo *info = GameData::get_instance()->getMusic()->getSongInfo(current_track);
00135 
00136                 uint32 measure = driver->getSequenceCallbackData(0);
00137 
00138                 // No transition info, or invalid measure, so fast change
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                 // Get transition info
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                 // Now get the transition midi
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                                         // if there's a track queued, only play this one once
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* /*args*/,
00296                                                                                 unsigned int /*argsize*/)
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 /*argsize*/)
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 // protection
00333 

Generated on Fri Jul 27 22:27:26 2007 for pentagram by  doxygen 1.4.7