Files
Aerofoil/GpApp/Music.cpp

384 lines
8.1 KiB
C++
Raw Normal View History

2019-11-11 00:11:59 -05:00
//============================================================================
//----------------------------------------------------------------------------
// Music.c
//----------------------------------------------------------------------------
//============================================================================
2020-01-24 02:09:19 -05:00
#include "DialogManager.h"
2019-11-11 00:11:59 -05:00
#include "Environ.h"
#include "Externs.h"
2019-12-26 13:12:56 -05:00
#include "SoundSync.h"
#include "IGpAudioBuffer.h"
#include "IGpMutex.h"
#include "IGpSystemServices.h"
2019-12-31 04:49:38 -05:00
#include "MemoryManager.h"
#include "ResourceManager.h"
2019-11-11 00:11:59 -05:00
#include "PLDrivers.h"
#include "PLResources.h"
#include "PLSound.h"
2019-11-11 00:11:59 -05:00
#define kBaseBufferMusicID 2000
#define kMaxMusic 7
#define kLastMusicPiece 16
#define kLastGamePiece 6
2019-12-31 04:49:38 -05:00
void MusicCallBack (PortabilityLayer::AudioChannel *channel);
2019-12-29 06:38:18 -05:00
PLError_t LoadMusicSounds (void);
PLError_t DumpMusicSounds (void);
PLError_t OpenMusicChannel (void);
PLError_t CloseMusicChannel (void);
2019-11-11 00:11:59 -05:00
IGpAudioBuffer *ParseAndConvertSound(const THandle<void> &handle);
2019-11-11 00:11:59 -05:00
2019-12-31 04:49:38 -05:00
PortabilityLayer::AudioChannel *musicChannel;
IGpAudioBuffer *theMusicData[kMaxMusic];
2019-11-11 00:11:59 -05:00
short musicScore[kLastMusicPiece];
short gameScore[kLastGamePiece];
Boolean isMusicOn, isPlayMusicIdle, isPlayMusicGame;
Boolean failedMusic, dontLoadMusic;
2019-12-26 13:12:56 -05:00
// Anything accessed from this must do so under the mutex lock, unless music is stopped
struct MusicState
{
short musicMode;
short musicSoundID, musicCursor;
};
MusicState musicState;
IGpMutex *musicMutex;
2019-12-26 13:12:56 -05:00
2019-11-11 00:11:59 -05:00
extern Boolean isSoundOn;
//============================================================== Functions
//-------------------------------------------------------------- StartMusic
2019-12-29 06:38:18 -05:00
PLError_t StartMusic (void)
2019-11-11 00:11:59 -05:00
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2019-11-11 00:11:59 -05:00
short soundVolume;
2020-10-12 00:37:32 -04:00
2019-12-29 06:38:18 -05:00
theErr = PLErrors::kNone;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (dontLoadMusic)
return(theErr);
2019-12-26 13:12:56 -05:00
if (musicMutex == nullptr)
return(theErr);
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
UnivGetSoundVolume(&soundVolume, thisMac.hasSM3);
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if ((soundVolume != 0) && (!failedMusic))
{
2019-12-31 04:49:38 -05:00
musicChannel->AddBuffer(theMusicData[musicState.musicSoundID], true);
// Don't need to lock here because the callback should not trigger until queued
2019-12-26 13:12:56 -05:00
musicState.musicCursor++;
if (musicState.musicCursor >= kLastMusicPiece)
musicState.musicCursor = 0;
musicState.musicSoundID = musicScore[musicState.musicCursor];
2019-12-31 04:49:38 -05:00
musicChannel->AddBuffer(theMusicData[musicState.musicSoundID], true);
musicChannel->AddCallback(MusicCallBack, true);
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
isMusicOn = true;
}
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
return (theErr);
}
//-------------------------------------------------------------- StopTheMusic
void StopTheMusic (void)
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (dontLoadMusic)
return;
2020-10-12 00:37:32 -04:00
2019-12-29 06:38:18 -05:00
theErr = PLErrors::kNone;
2019-11-11 00:11:59 -05:00
if ((isMusicOn) && (!failedMusic))
{
2019-12-31 04:49:38 -05:00
musicChannel->ClearAllCommands();
musicChannel->Stop();
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
isMusicOn = false;
}
}
//-------------------------------------------------------------- ToggleMusicWhilePlaying
void ToggleMusicWhilePlaying (void)
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (dontLoadMusic)
return;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (isPlayMusicGame)
{
if (!isMusicOn)
theErr = StartMusic();
}
else
{
if (isMusicOn)
StopTheMusic();
}
}
//-------------------------------------------------------------- SetMusicalPiece
void SetMusicalMode (short newMode)
2020-10-12 00:37:32 -04:00
{
if (dontLoadMusic || failedMusic)
2019-11-11 00:11:59 -05:00
return;
2019-12-26 13:12:56 -05:00
musicMutex->Lock();
2019-11-11 00:11:59 -05:00
switch (newMode)
{
case kKickGameScoreMode:
2019-12-26 13:12:56 -05:00
musicState.musicCursor = 2;
2019-11-11 00:11:59 -05:00
break;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
case kProdGameScoreMode:
2019-12-26 13:12:56 -05:00
musicState.musicCursor = -1;
2019-11-11 00:11:59 -05:00
break;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
default:
2019-12-26 13:12:56 -05:00
musicState.musicMode = newMode;
musicState.musicCursor = 0;
2019-11-11 00:11:59 -05:00
break;
}
2019-12-26 13:12:56 -05:00
musicMutex->Unlock();
2019-11-11 00:11:59 -05:00
}
//-------------------------------------------------------------- MusicCallBack
2019-12-31 04:49:38 -05:00
void MusicCallBack (PortabilityLayer::AudioChannel *theChannel)
2019-11-11 00:11:59 -05:00
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2019-12-26 13:12:56 -05:00
musicMutex->Lock();
switch (musicState.musicMode)
2019-11-11 00:11:59 -05:00
{
case kPlayGameScoreMode:
2019-12-26 13:12:56 -05:00
musicState.musicCursor++;
if (musicState.musicCursor >= kLastGamePiece)
musicState.musicCursor = 1;
musicState.musicSoundID = gameScore[musicState.musicCursor];
if (musicState.musicSoundID < 0)
2019-11-11 00:11:59 -05:00
{
2019-12-26 13:12:56 -05:00
musicState.musicCursor += musicState.musicSoundID;
musicState.musicSoundID = gameScore[musicState.musicCursor];
2019-11-11 00:11:59 -05:00
}
break;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
case kPlayWholeScoreMode:
2019-12-26 13:12:56 -05:00
musicState.musicCursor++;
if (musicState.musicCursor >= kLastMusicPiece - 1)
musicState.musicCursor = 0;
musicState.musicSoundID = musicScore[musicState.musicCursor];
2019-11-11 00:11:59 -05:00
break;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
default:
2019-12-26 13:12:56 -05:00
musicState.musicSoundID = musicState.musicMode;
2019-11-11 00:11:59 -05:00
break;
}
2019-12-26 13:12:56 -05:00
short musicSoundID = musicState.musicSoundID;
musicMutex->Unlock();
2019-12-31 04:49:38 -05:00
theChannel->AddBuffer(theMusicData[musicSoundID], true);
theChannel->AddCallback(MusicCallBack, true);
2019-11-11 00:11:59 -05:00
}
//-------------------------------------------------------------- LoadMusicSounds
2019-12-29 06:38:18 -05:00
PLError_t LoadMusicSounds (void)
2019-11-11 00:11:59 -05:00
{
Handle theSound;
long soundDataSize;
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2019-11-11 00:11:59 -05:00
short i;
2020-10-12 00:37:32 -04:00
2019-12-29 06:38:18 -05:00
theErr = PLErrors::kNone;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
for (i = 0; i < kMaxMusic; i++)
{
assert(theMusicData[i] == nil);
}
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
for (i = 0; i < kMaxMusic; i++)
{
theSound = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('snd ', i + kBaseBufferMusicID);
2019-11-11 00:11:59 -05:00
if (theSound == nil)
2019-12-29 06:38:18 -05:00
return PLErrors::kOutOfMemory;
2020-10-12 00:37:32 -04:00
IGpAudioBuffer *buffer = ParseAndConvertSound(theSound);
theSound.Dispose();
if (buffer == nil)
2019-12-29 06:38:18 -05:00
return PLErrors::kOutOfMemory;
theMusicData[i] = buffer;
2019-11-11 00:11:59 -05:00
}
return (theErr);
}
//-------------------------------------------------------------- DumpMusicSounds
2019-12-29 06:38:18 -05:00
PLError_t DumpMusicSounds (void)
2019-11-11 00:11:59 -05:00
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2019-11-11 00:11:59 -05:00
short i;
2020-10-12 00:37:32 -04:00
2019-12-29 06:38:18 -05:00
theErr = PLErrors::kNone;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
for (i = 0; i < kMaxMusic; i++)
{
if (theMusicData[i] != nil)
theMusicData[i]->Release();
2019-11-11 00:11:59 -05:00
theMusicData[i] = nil;
}
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
return (theErr);
}
//-------------------------------------------------------------- OpenMusicChannel
2019-12-29 06:38:18 -05:00
PLError_t OpenMusicChannel (void)
2019-11-11 00:11:59 -05:00
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2020-10-12 00:37:32 -04:00
2019-12-29 06:38:18 -05:00
theErr = PLErrors::kNone;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (musicChannel != nil)
return (theErr);
2020-10-12 00:37:32 -04:00
2019-12-31 04:49:38 -05:00
musicChannel = PortabilityLayer::SoundSystem::GetInstance()->CreateChannel();
if (musicChannel == nil)
theErr = PLErrors::kAudioError;
2019-11-11 00:11:59 -05:00
return (theErr);
}
//-------------------------------------------------------------- CloseMusicChannel
2019-12-29 06:38:18 -05:00
PLError_t CloseMusicChannel (void)
2019-11-11 00:11:59 -05:00
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2020-10-12 00:37:32 -04:00
2019-12-29 06:38:18 -05:00
theErr = PLErrors::kNone;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (musicChannel != nil)
2019-12-31 04:49:38 -05:00
musicChannel->Destroy(false);
2019-11-11 00:11:59 -05:00
musicChannel = nil;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
return (theErr);
}
//-------------------------------------------------------------- InitMusic
void InitMusic (void)
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (dontLoadMusic)
return;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
musicChannel = nil;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
failedMusic = false;
isMusicOn = false;
theErr = LoadMusicSounds();
2019-12-29 06:38:18 -05:00
if (theErr != PLErrors::kNone)
2019-11-11 00:11:59 -05:00
{
YellowAlert(kYellowNoMusic, theErr);
failedMusic = true;
return;
}
theErr = OpenMusicChannel();
if (theErr != PLErrors::kNone)
{
YellowAlert(kYellowNoMusic, theErr);
failedMusic = true;
return;
}
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
musicScore[0] = 0;
musicScore[1] = 1;
musicScore[2] = 2;
musicScore[3] = 3;
musicScore[4] = 4;
musicScore[5] = 4;
musicScore[6] = 0;
musicScore[7] = 1;
musicScore[8] = 2;
musicScore[9] = 3;
musicScore[10] = kPlayChorus;
musicScore[11] = kPlayChorus;
musicScore[12] = kPlayRefrainSparse1;
musicScore[13] = kPlayRefrainSparse2;
musicScore[14] = kPlayChorus;
musicScore[15] = kPlayChorus;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
gameScore[0] = kPlayRefrainSparse2;
gameScore[1] = kPlayRefrainSparse1;
gameScore[2] = -1;
gameScore[3] = kPlayRefrainSparse2;
gameScore[4] = kPlayChorus;
gameScore[5] = kPlayChorus;
2020-10-12 00:37:32 -04:00
2019-12-26 13:12:56 -05:00
musicState.musicCursor = 0;
musicState.musicSoundID = musicScore[musicState.musicCursor];
musicState.musicMode = kPlayWholeScoreMode;
musicMutex = PLDrivers::GetSystemServices()->CreateMutex();
2019-12-25 22:20:10 -05:00
PL_NotYetImplemented_TODO("MusicSync");
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (isPlayMusicIdle)
{
theErr = StartMusic();
2019-12-29 06:38:18 -05:00
if (theErr != PLErrors::kNone)
2019-11-11 00:11:59 -05:00
{
YellowAlert(kYellowNoMusic, theErr);
failedMusic = true;
}
}
}
//-------------------------------------------------------------- KillMusic
void KillMusic (void)
{
2019-12-29 06:38:18 -05:00
PLError_t theErr;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
if (dontLoadMusic)
return;
2020-01-18 18:39:54 -05:00
2019-11-11 00:11:59 -05:00
theErr = CloseMusicChannel();
2020-01-18 18:39:54 -05:00
theErr = DumpMusicSounds();
2020-10-12 00:37:32 -04:00
if (musicMutex)
musicMutex->Destroy();
2019-11-11 00:11:59 -05:00
}
//-------------------------------------------------------------- TellHerNoMusic
void TellHerNoMusic (void)
{
#define kNoMemForMusicAlert 1038
short hitWhat;
2020-10-12 00:37:32 -04:00
2019-11-11 00:11:59 -05:00
// CenterAlert(kNoMemForMusicAlert);
hitWhat = PortabilityLayer::DialogManager::GetInstance()->DisplayAlert(kNoMemForMusicAlert, nullptr);
2019-11-11 00:11:59 -05:00
}