1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-11 00:39:59 +00:00
OpenMW/mscripts/sound/jukebox.mn
2009-01-22 20:36:36 +00:00

225 lines
4.2 KiB
Plaintext

/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (jukebox.mn) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
/*
A simple jukebox with a playlist. It can play, stop, pause with
fade in and fade out, and adjust volume.
*/
class Jukebox;
// Between 0 (off) and 1 (full volume)
float fadeLevel = 0.0;
// How much to fade in and out each second
float fadeInRate = 0.14;
float fadeOutRate = 0.30;
// Time between each fade step
float fadeInterval = 0.2;
// List of sounds to play
char[][] playlist;
// Name used for error messages
char[] name;
// Index of current song
int index;
// The music volume, set by the user. Does NOT change to adjust for
// fading, it is only updated when the user changes the volume
// settings. Updated from Config through updateVolume().
float musVolume;
bool isPlaying; // Is a song currently playing?
bool isPaused; // Is the song currently paused?
// Native functions to control music
native setSound(char[] filename);
native setVolume(float f);
native playSound();
native stopSound();
idle waitUntilFinished();
// Fade out and then stop the music. TODO: Rename these to resume()
// etc and use super.resume, when this is possible.
pause()
{
isPaused = true;
state = fadeOut;
}
resume()
{
if(!Config.useMusic) return;
if(isPaused) playSound();
else next();
isPaused = false;
state = fadeIn;
}
// Stop the current song. Calling resume again after this is called
// will start a new song.
stop()
{
stopSound();
isPlaying = false;
fadeLevel = 0.0;
state = null;
}
play()
{
if(!Config.useMusic) return;
if(index >= playlist.length)
return;
setSound(playlist[index]);
setVolume(musVolume*fadeLevel);
playSound();
isPlaying = true;
isPaused = false;
state = playing;
}
// Play the next song in the playlist
next()
{
if(!Config.useMusic) return;
if(isPlaying)
stop();
// Find the index of the next song, if any
if(playlist.length == 0) return;
if(++index >= playlist.length)
{
index = 0;
randomize();
}
play();
}
// Set the new music volume setting.
updateVolume(float f)
{
musVolume = f;
if(isPlaying)
setVolume(musVolume*fadeLevel);
}
setPlaylist(char[][] lst)
{
playlist = lst;
randomize();
}
// Randomize playlist.
randomize()
{
if(playlist.length < 2) return;
foreach(int i, char[] s; playlist)
{
// Index to switch with
int idx = randInt(i,playlist.length-1);
// To avoid playing the same song twice in a row, don't set the
// first song to the previous last.
if(i == 0 && idx == playlist.length-1)
idx--;
if(idx == i) // Skip if swapping with self
continue;
playlist[i] = playlist[idx];
playlist[idx] = s;
}
}
// Fade in
state fadeIn
{
begin:
setVolume(musVolume*fadeLevel);
sleep(fadeInterval);
fadeLevel += fadeInterval*fadeInRate;
if(fadeLevel >= 1.0)
{
fadeLevel = 1.0;
setVolume(musVolume);
state = playing;
}
goto begin;
}
// Fade out
state fadeOut
{
begin:
sleep(fadeInterval);
fadeLevel -= fadeInterval*fadeOutRate;
if(fadeLevel <= 0.0)
{
fadeLevel = 0.0;
stopSound();
isPlaying = false;
state = null;
}
setVolume(musVolume*fadeLevel);
goto begin;
}
state playing
{
begin:
setVolume(musVolume);
fadeLevel = 1.0;
while(true)
{
// Wait for the song to play. Will return imediately if the song has
// already stopped or if no song is playing
waitUntilFinished();
// Start playing the next song
next();
}
}