mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 06:53:43 +00:00
393 lines
8.6 KiB
C++
393 lines
8.6 KiB
C++
//============================================================================
|
|
//----------------------------------------------------------------------------
|
|
// Music.c
|
|
//----------------------------------------------------------------------------
|
|
//============================================================================
|
|
|
|
|
|
#include "PLResources.h"
|
|
#include "PLSound.h"
|
|
#include "DialogManager.h"
|
|
#include "Environ.h"
|
|
#include "Externs.h"
|
|
#include "SoundSync.h"
|
|
#include "HostMutex.h"
|
|
#include "HostSystemServices.h"
|
|
#include "MemoryManager.h"
|
|
#include "ResourceManager.h"
|
|
|
|
|
|
#define kBaseBufferMusicID 2000
|
|
#define kMaxMusic 7
|
|
#define kLastMusicPiece 16
|
|
#define kLastGamePiece 6
|
|
|
|
|
|
void MusicCallBack (PortabilityLayer::AudioChannel *channel);
|
|
PLError_t LoadMusicSounds (void);
|
|
PLError_t DumpMusicSounds (void);
|
|
PLError_t OpenMusicChannel (void);
|
|
PLError_t CloseMusicChannel (void);
|
|
|
|
THandle<void> ParseAndConvertSound(const THandle<void> &handle);
|
|
|
|
|
|
PortabilityLayer::AudioChannel *musicChannel;
|
|
Ptr theMusicData[kMaxMusic];
|
|
short musicScore[kLastMusicPiece];
|
|
short gameScore[kLastGamePiece];
|
|
Boolean isMusicOn, isPlayMusicIdle, isPlayMusicGame;
|
|
Boolean failedMusic, dontLoadMusic;
|
|
|
|
// Anything accessed from this must do so under the mutex lock, unless music is stopped
|
|
struct MusicState
|
|
{
|
|
short musicMode;
|
|
short musicSoundID, musicCursor;
|
|
};
|
|
|
|
MusicState musicState;
|
|
PortabilityLayer::HostMutex *musicMutex;
|
|
|
|
|
|
extern Boolean isSoundOn;
|
|
|
|
|
|
//============================================================== Functions
|
|
//-------------------------------------------------------------- StartMusic
|
|
|
|
PLError_t StartMusic (void)
|
|
{
|
|
PLError_t theErr;
|
|
short soundVolume;
|
|
|
|
theErr = PLErrors::kNone;
|
|
|
|
if (dontLoadMusic)
|
|
return(theErr);
|
|
|
|
if (musicMutex == nullptr)
|
|
return(theErr);
|
|
|
|
UnivGetSoundVolume(&soundVolume, thisMac.hasSM3);
|
|
|
|
if ((soundVolume != 0) && (!failedMusic))
|
|
{
|
|
musicChannel->AddBuffer(theMusicData[musicState.musicSoundID], true);
|
|
|
|
// Don't need to lock here because the callback should not trigger until queued
|
|
musicState.musicCursor++;
|
|
if (musicState.musicCursor >= kLastMusicPiece)
|
|
musicState.musicCursor = 0;
|
|
musicState.musicSoundID = musicScore[musicState.musicCursor];
|
|
|
|
musicChannel->AddBuffer(theMusicData[musicState.musicSoundID], true);
|
|
musicChannel->AddCallback(MusicCallBack, true);
|
|
|
|
isMusicOn = true;
|
|
}
|
|
|
|
return (theErr);
|
|
}
|
|
|
|
//-------------------------------------------------------------- StopTheMusic
|
|
|
|
void StopTheMusic (void)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
if (dontLoadMusic)
|
|
return;
|
|
|
|
theErr = PLErrors::kNone;
|
|
if ((isMusicOn) && (!failedMusic))
|
|
{
|
|
musicChannel->ClearAllCommands();
|
|
musicChannel->Stop();
|
|
|
|
isMusicOn = false;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------- ToggleMusicWhilePlaying
|
|
|
|
void ToggleMusicWhilePlaying (void)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
if (dontLoadMusic)
|
|
return;
|
|
|
|
if (isPlayMusicGame)
|
|
{
|
|
if (!isMusicOn)
|
|
theErr = StartMusic();
|
|
}
|
|
else
|
|
{
|
|
if (isMusicOn)
|
|
StopTheMusic();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------- SetMusicalPiece
|
|
|
|
void SetMusicalMode (short newMode)
|
|
{
|
|
if (dontLoadMusic)
|
|
return;
|
|
|
|
musicMutex->Lock();
|
|
switch (newMode)
|
|
{
|
|
case kKickGameScoreMode:
|
|
musicState.musicCursor = 2;
|
|
break;
|
|
|
|
case kProdGameScoreMode:
|
|
musicState.musicCursor = -1;
|
|
break;
|
|
|
|
default:
|
|
musicState.musicMode = newMode;
|
|
musicState.musicCursor = 0;
|
|
break;
|
|
}
|
|
musicMutex->Unlock();
|
|
}
|
|
|
|
//-------------------------------------------------------------- MusicCallBack
|
|
|
|
void MusicCallBack (PortabilityLayer::AudioChannel *theChannel)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
musicMutex->Lock();
|
|
switch (musicState.musicMode)
|
|
{
|
|
case kPlayGameScoreMode:
|
|
musicState.musicCursor++;
|
|
if (musicState.musicCursor >= kLastGamePiece)
|
|
musicState.musicCursor = 1;
|
|
musicState.musicSoundID = gameScore[musicState.musicCursor];
|
|
if (musicState.musicSoundID < 0)
|
|
{
|
|
musicState.musicCursor += musicState.musicSoundID;
|
|
musicState.musicSoundID = gameScore[musicState.musicCursor];
|
|
}
|
|
break;
|
|
|
|
case kPlayWholeScoreMode:
|
|
musicState.musicCursor++;
|
|
if (musicState.musicCursor >= kLastMusicPiece - 1)
|
|
musicState.musicCursor = 0;
|
|
musicState.musicSoundID = musicScore[musicState.musicCursor];
|
|
break;
|
|
|
|
default:
|
|
musicState.musicSoundID = musicState.musicMode;
|
|
break;
|
|
}
|
|
|
|
short musicSoundID = musicState.musicSoundID;
|
|
musicMutex->Unlock();
|
|
|
|
theChannel->AddBuffer(theMusicData[musicSoundID], true);
|
|
theChannel->AddCallback(MusicCallBack, true);
|
|
}
|
|
|
|
//-------------------------------------------------------------- LoadMusicSounds
|
|
|
|
PLError_t LoadMusicSounds (void)
|
|
{
|
|
Handle theSound;
|
|
long soundDataSize;
|
|
PLError_t theErr;
|
|
short i;
|
|
|
|
theErr = PLErrors::kNone;
|
|
|
|
for (i = 0; i < kMaxMusic; i++)
|
|
theMusicData[i] = nil;
|
|
|
|
for (i = 0; i < kMaxMusic; i++)
|
|
{
|
|
theSound = ParseAndConvertSound(PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('snd ', i + kBaseBufferMusicID));
|
|
if (theSound == nil)
|
|
return PLErrors::kOutOfMemory;
|
|
|
|
soundDataSize = GetHandleSize(theSound);
|
|
|
|
theMusicData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize);
|
|
if (theMusicData[i] == nil)
|
|
return PLErrors::kOutOfMemory;
|
|
|
|
BlockMove(static_cast<Byte*>(*theSound), theMusicData[i], soundDataSize);
|
|
theSound.Dispose();
|
|
}
|
|
return (theErr);
|
|
}
|
|
|
|
//-------------------------------------------------------------- DumpMusicSounds
|
|
|
|
PLError_t DumpMusicSounds (void)
|
|
{
|
|
PLError_t theErr;
|
|
short i;
|
|
|
|
theErr = PLErrors::kNone;
|
|
|
|
for (i = 0; i < kMaxMusic; i++)
|
|
{
|
|
if (theMusicData[i] != nil)
|
|
PortabilityLayer::MemoryManager::GetInstance()->Release(theMusicData[i]);
|
|
theMusicData[i] = nil;
|
|
}
|
|
|
|
return (theErr);
|
|
}
|
|
|
|
//-------------------------------------------------------------- OpenMusicChannel
|
|
|
|
PLError_t OpenMusicChannel (void)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
theErr = PLErrors::kNone;
|
|
|
|
if (musicChannel != nil)
|
|
return (theErr);
|
|
|
|
musicChannel = PortabilityLayer::SoundSystem::GetInstance()->CreateChannel();
|
|
|
|
if (musicChannel == nil)
|
|
theErr = PLErrors::kAudioError;
|
|
|
|
return (theErr);
|
|
}
|
|
|
|
//-------------------------------------------------------------- CloseMusicChannel
|
|
|
|
PLError_t CloseMusicChannel (void)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
theErr = PLErrors::kNone;
|
|
|
|
if (musicChannel != nil)
|
|
musicChannel->Destroy(false);
|
|
musicChannel = nil;
|
|
|
|
return (theErr);
|
|
}
|
|
|
|
//-------------------------------------------------------------- InitMusic
|
|
|
|
void InitMusic (void)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
if (dontLoadMusic)
|
|
return;
|
|
|
|
musicChannel = nil;
|
|
|
|
failedMusic = false;
|
|
isMusicOn = false;
|
|
theErr = LoadMusicSounds();
|
|
if (theErr != PLErrors::kNone)
|
|
{
|
|
YellowAlert(kYellowNoMusic, theErr);
|
|
failedMusic = true;
|
|
return;
|
|
}
|
|
theErr = OpenMusicChannel();
|
|
|
|
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;
|
|
|
|
gameScore[0] = kPlayRefrainSparse2;
|
|
gameScore[1] = kPlayRefrainSparse1;
|
|
gameScore[2] = -1;
|
|
gameScore[3] = kPlayRefrainSparse2;
|
|
gameScore[4] = kPlayChorus;
|
|
gameScore[5] = kPlayChorus;
|
|
|
|
musicState.musicCursor = 0;
|
|
musicState.musicSoundID = musicScore[musicState.musicCursor];
|
|
musicState.musicMode = kPlayWholeScoreMode;
|
|
|
|
musicMutex = PortabilityLayer::HostSystemServices::GetInstance()->CreateMutex();
|
|
|
|
PL_NotYetImplemented_TODO("MusicSync");
|
|
|
|
if (isPlayMusicIdle)
|
|
{
|
|
theErr = StartMusic();
|
|
if (theErr != PLErrors::kNone)
|
|
{
|
|
YellowAlert(kYellowNoMusic, theErr);
|
|
failedMusic = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------- KillMusic
|
|
|
|
void KillMusic (void)
|
|
{
|
|
PLError_t theErr;
|
|
|
|
if (dontLoadMusic)
|
|
return;
|
|
|
|
theErr = CloseMusicChannel();
|
|
theErr = DumpMusicSounds();
|
|
musicMutex->Destroy();
|
|
}
|
|
|
|
//-------------------------------------------------------------- MusicBytesNeeded
|
|
|
|
long MusicBytesNeeded (void)
|
|
{
|
|
size_t totalBytes;
|
|
short i;
|
|
|
|
totalBytes = 0L;
|
|
for (i = 0; i < kMaxMusic; i++)
|
|
{
|
|
size_t resSize = 0;
|
|
if (!PortabilityLayer::ResourceManager::GetInstance()->GetAppResourceArchive()->GetResourceSize('snd ', i + kBaseBufferMusicID, resSize))
|
|
return -1;
|
|
|
|
totalBytes += static_cast<long>(resSize);
|
|
}
|
|
return totalBytes;
|
|
}
|
|
|
|
//-------------------------------------------------------------- TellHerNoMusic
|
|
|
|
void TellHerNoMusic (void)
|
|
{
|
|
#define kNoMemForMusicAlert 1038
|
|
short hitWhat;
|
|
|
|
// CenterAlert(kNoMemForMusicAlert);
|
|
hitWhat = PortabilityLayer::DialogManager::GetInstance()->DisplayAlert(kNoMemForMusicAlert);
|
|
}
|
|
|