nekonomicon
2 years ago
committed by
GitHub
21 changed files with 621 additions and 2751 deletions
@ -1,3 +1,7 @@ |
|||||||
[submodule "vgui_support"] |
[submodule "vgui_support"] |
||||||
path = vgui_support |
path = vgui_support |
||||||
url = https://github.com/FWGS/vgui_support |
url = https://github.com/FWGS/vgui_support |
||||||
|
|
||||||
|
[submodule "miniaudio"] |
||||||
|
path = miniaudio |
||||||
|
url = https://github.com/mackron/miniaudio |
||||||
|
@ -0,0 +1,443 @@ |
|||||||
|
//-------------------------------------------------------------
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-
|
||||||
|
//- clientmusic.cpp
|
||||||
|
//-
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//- by Roy at suggestion by nekonomicon, based on code by JujU
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//- mp3 player code for HL mod
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-
|
||||||
|
//- compatible with version 0.11.9 of Miniaudio
|
||||||
|
//- https://github.com/mackron/miniaudio
|
||||||
|
//-
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
Don't forget to update the miniaudio submodule. |
||||||
|
|
||||||
|
Miniaudio 0.11.9 or better required. |
||||||
|
|
||||||
|
Tested on Debian. |
||||||
|
|
||||||
|
For playlist format see the bottom of the file. |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// inclusions
|
||||||
|
|
||||||
|
|
||||||
|
#include "hud.h" |
||||||
|
#include "cl_util.h" |
||||||
|
#include "const.h" |
||||||
|
#include "parsemsg.h" |
||||||
|
|
||||||
|
#ifndef DISABLE_MINIAUDIO //Use this to exclude the player in it's entirety. Will use empty "trigger_music" with no playback.
|
||||||
|
#include "clientmusic.h" |
||||||
|
|
||||||
|
CMusic g_MusicPlayer; //Instantiate.
|
||||||
|
|
||||||
|
//These are just initial ones. If the actual track has different ones, they will be re-applied during Play().
|
||||||
|
#define SAMPLE_FORMAT ma_format_f32 |
||||||
|
#define CHANNEL_COUNT 2 |
||||||
|
#define SAMPLE_RATE 48000 |
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// implementation CHudMusic class methods (defined in hud.h)
|
||||||
|
|
||||||
|
//CHudMusic is declared in hud.h and is needed to receive messages.
|
||||||
|
//hud.cpp also contains and Init function call.
|
||||||
|
//The implementation goes here:
|
||||||
|
|
||||||
|
#endif //The code above can be disabled if we don't actually use a music player, but this
|
||||||
|
//section here must be present anyway, since we need to implement things hud.h and hud.cpp
|
||||||
|
//expect us to implement.
|
||||||
|
|
||||||
|
DECLARE_MESSAGE(m_MusicPlayer, CMusicOpen ); |
||||||
|
|
||||||
|
int CHudMusic :: Init( void ){ |
||||||
|
HOOK_MESSAGE( CMusicOpen ); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
int CHudMusic :: MsgFunc_CMusicOpen ( const char *pszName, int iSize, void *pbuf ){ |
||||||
|
|
||||||
|
char* fnString; |
||||||
|
char filename[512]; |
||||||
|
int filetype = 0; |
||||||
|
|
||||||
|
BEGIN_READ( pbuf, iSize ); |
||||||
|
filetype = READ_BYTE(); |
||||||
|
fnString = READ_STRING(); |
||||||
|
|
||||||
|
sprintf(filename,"%s",fnString); |
||||||
|
|
||||||
|
#ifndef DISABLE_MINIAUDIO //This part must only be present if we actually have a music player.
|
||||||
|
//gEngfuncs.Con_Printf ( "MUSICPLAYER : Received message from server: File type is %d, file name is: %s\n", filetype, filename );
|
||||||
|
|
||||||
|
if(filetype != MUSIC_AUDIO_FILE) |
||||||
|
g_MusicPlayer.OpenList ( filename ); |
||||||
|
else |
||||||
|
g_MusicPlayer.OpenFile ( filename, 1 ); |
||||||
|
g_MusicPlayer.Play(); |
||||||
|
|
||||||
|
#else //Otherwise we do nothing here.
|
||||||
|
//gEngfuncs.Con_Printf ( "MUSICPLAYER : Received message, but player is disabled. Discarding.\n" );
|
||||||
|
#endif |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
#ifndef DISABLE_MINIAUDIO //The code below can, once again, be disabled if we don't
|
||||||
|
//actually use a music player.
|
||||||
|
|
||||||
|
//Define callback, so we can use it during init. The implementation can be found below.
|
||||||
|
void CMusic_DecoderCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount); |
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// initialisation
|
||||||
|
|
||||||
|
void CMusic :: Init ( void ) |
||||||
|
{ |
||||||
|
if( m_bInit == true ){ |
||||||
|
return; //Do not re-init.
|
||||||
|
} |
||||||
|
|
||||||
|
deviceConfig = ma_device_config_init(ma_device_type_playback); |
||||||
|
deviceConfig.playback.format = SAMPLE_FORMAT; |
||||||
|
deviceConfig.playback.channels = CHANNEL_COUNT; |
||||||
|
deviceConfig.sampleRate = SAMPLE_RATE; |
||||||
|
deviceConfig.dataCallback = CMusic_DecoderCallback; // this contains the callback that monitors the end of the song
|
||||||
|
deviceConfig.pUserData = NULL; |
||||||
|
|
||||||
|
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) { |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : unable to initialize\n" ); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
m_bInit = true; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Callback being called during playback
|
||||||
|
|
||||||
|
void CMusic_DecoderCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) |
||||||
|
{ |
||||||
|
if(g_MusicPlayer.m_IsPlaying == false){ |
||||||
|
return; //We are paused or stopped, let's exit now.
|
||||||
|
} |
||||||
|
|
||||||
|
ma_decoder* pDecoder = (ma_decoder*)&g_MusicPlayer.decoder; |
||||||
|
if (pDecoder == NULL) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if(frameCount<=0) return; |
||||||
|
|
||||||
|
ma_uint64 framesRead; |
||||||
|
|
||||||
|
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount, &framesRead); |
||||||
|
if(framesRead < frameCount) //This happens when the song ends.
|
||||||
|
g_MusicPlayer.songEnd(); |
||||||
|
|
||||||
|
(void)pInput; |
||||||
|
} |
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// playing an audio file
|
||||||
|
|
||||||
|
|
||||||
|
void CMusic :: OpenFile ( char *filename, int repeat ) |
||||||
|
{ |
||||||
|
audiofile_t *p = NULL; |
||||||
|
p = new audiofile_t; |
||||||
|
|
||||||
|
sprintf ( p->name, filename ); |
||||||
|
p->repeat = repeat; |
||||||
|
p->next = m_pTrack; |
||||||
|
|
||||||
|
m_pTrack = p; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// play a list of audio files
|
||||||
|
|
||||||
|
|
||||||
|
void CMusic :: OpenList ( char *filename ) |
||||||
|
{ |
||||||
|
|
||||||
|
// open text file
|
||||||
|
|
||||||
|
FILE *myfile = fopen ( filename, "r" ); |
||||||
|
|
||||||
|
if ( myfile == NULL ) |
||||||
|
{ |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : impossible to load %s\n", filename ); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// saving songs to the list
|
||||||
|
|
||||||
|
int total = 0; |
||||||
|
|
||||||
|
if ( fscanf ( myfile, "%i", &total ) != EOF ) |
||||||
|
{ |
||||||
|
for ( int i=0; i<total; i++ ) |
||||||
|
{ |
||||||
|
char ctitle [128]; |
||||||
|
int irepeat; |
||||||
|
|
||||||
|
// reading the title
|
||||||
|
|
||||||
|
if ( fscanf ( myfile, "%s", ctitle ) != EOF ) |
||||||
|
{ |
||||||
|
if ( fscanf ( myfile, "%i", &irepeat ) != EOF ) |
||||||
|
OpenFile ( ctitle, irepeat ); |
||||||
|
|
||||||
|
else |
||||||
|
break; |
||||||
|
} |
||||||
|
else |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// close text file
|
||||||
|
|
||||||
|
fclose ( myfile ); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// end of the song
|
||||||
|
|
||||||
|
|
||||||
|
void CMusic :: songEnd ( ) |
||||||
|
{ |
||||||
|
// end of the song
|
||||||
|
|
||||||
|
g_MusicPlayer.Stop (); |
||||||
|
|
||||||
|
// search for the first song in the list
|
||||||
|
|
||||||
|
audiofile_t *p = NULL; |
||||||
|
p = g_MusicPlayer.m_pTrack; |
||||||
|
|
||||||
|
while ( p != NULL ) |
||||||
|
{ |
||||||
|
if ( p->next == NULL ) |
||||||
|
break; |
||||||
|
else |
||||||
|
p = p->next; |
||||||
|
} |
||||||
|
|
||||||
|
if ( p == NULL ) |
||||||
|
{ |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : no song in the list\n" ); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// decrease repeat count
|
||||||
|
|
||||||
|
p->repeat --; |
||||||
|
|
||||||
|
// removal of songs whose repeats ran off
|
||||||
|
|
||||||
|
if ( p->repeat < 1 ) |
||||||
|
{ |
||||||
|
if ( g_MusicPlayer.m_pTrack == p ) |
||||||
|
{ |
||||||
|
delete g_MusicPlayer.m_pTrack; |
||||||
|
g_MusicPlayer.m_pTrack = NULL; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
audiofile_t *q = NULL; |
||||||
|
q = g_MusicPlayer.m_pTrack; |
||||||
|
|
||||||
|
while ( q->next != p ) |
||||||
|
q = q->next; |
||||||
|
|
||||||
|
delete q->next; |
||||||
|
q->next = NULL; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// close player if list is empty
|
||||||
|
|
||||||
|
if ( g_MusicPlayer.m_pTrack == NULL ) |
||||||
|
{ |
||||||
|
g_MusicPlayer.Reset(); |
||||||
|
} |
||||||
|
|
||||||
|
// next track start
|
||||||
|
|
||||||
|
else |
||||||
|
{ |
||||||
|
g_MusicPlayer.Play(); |
||||||
|
} |
||||||
|
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// initiate playback
|
||||||
|
|
||||||
|
|
||||||
|
void CMusic :: Play ( void ) |
||||||
|
{ |
||||||
|
if ( m_IsPlaying == true ) |
||||||
|
return; |
||||||
|
|
||||||
|
if ( m_bInit == false ) |
||||||
|
{ |
||||||
|
Init (); |
||||||
|
|
||||||
|
if ( m_bInit == false ) |
||||||
|
{ |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : unable to initialize\n" ); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// search for the first song in the list
|
||||||
|
|
||||||
|
audiofile_t *p = NULL; |
||||||
|
p = m_pTrack; |
||||||
|
|
||||||
|
while ( p != NULL ) |
||||||
|
{ |
||||||
|
if ( p->next == NULL ) |
||||||
|
break; |
||||||
|
else |
||||||
|
p = p->next; |
||||||
|
} |
||||||
|
|
||||||
|
if ( p == NULL ) |
||||||
|
{ |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : no song in the list\n" ); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//Stop playback
|
||||||
|
m_IsPlaying = false; //Pause playback.
|
||||||
|
ma_decoder_seek_to_pcm_frame(&decoder, 0); //Reset the file to start.
|
||||||
|
|
||||||
|
// loading file
|
||||||
|
char payload [512]; |
||||||
|
sprintf(payload, "%s", p->name); |
||||||
|
|
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : Opening file %s.\n", payload ); |
||||||
|
|
||||||
|
result = ma_decoder_init_file(payload, NULL, &decoder); |
||||||
|
if (result != MA_SUCCESS) { |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : %s : can not load file\n", p->name ); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//If the new track has different properties to the previous one.
|
||||||
|
if( |
||||||
|
deviceConfig.playback.format != decoder.outputFormat || |
||||||
|
deviceConfig.playback.channels != decoder.outputChannels || |
||||||
|
deviceConfig.sampleRate != decoder.outputSampleRate |
||||||
|
){ |
||||||
|
deviceConfig.playback.format = decoder.outputFormat; //Change device settings
|
||||||
|
deviceConfig.playback.channels = decoder.outputChannels; |
||||||
|
deviceConfig.sampleRate = decoder.outputSampleRate; |
||||||
|
|
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : Changing format to %d, channels to %d and sample rate to %d.\n", deviceConfig.playback.format, deviceConfig.playback.channels, deviceConfig.sampleRate); |
||||||
|
|
||||||
|
//Now we need to recreate the device to apply.
|
||||||
|
ma_device_uninit(&device); //This is crucial, failing to do this results in segFault.
|
||||||
|
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) { //Apply new config.
|
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : Failed to change playback device configuration.\n" ); |
||||||
|
g_MusicPlayer.m_bInit = false; //We have been deinitialized. This is NOT ideal.
|
||||||
|
return; |
||||||
|
}else |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : New configuration applied successfully.\n"); |
||||||
|
} |
||||||
|
|
||||||
|
// playback
|
||||||
|
if (ma_device_start(&device) != MA_SUCCESS) { |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : Failed to start playback device.\n" ); |
||||||
|
m_IsPlaying = false; //Pause playback.
|
||||||
|
ma_decoder_seek_to_pcm_frame(&decoder, 0); //Reset the file to start.
|
||||||
|
return; |
||||||
|
}else{ |
||||||
|
m_IsPlaying = true; |
||||||
|
} |
||||||
|
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void CMusic :: Stop ( void ) |
||||||
|
{ |
||||||
|
if ( m_IsPlaying == true ) |
||||||
|
{ |
||||||
|
m_IsPlaying = false; //Pause playback.
|
||||||
|
ma_decoder_seek_to_pcm_frame(&decoder, 0); //Reset the file to start.
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void CMusic :: Reset ( void ) //Should instead be called "Next Track", but we keep Julien's naming.
|
||||||
|
{ |
||||||
|
//Reset the player.
|
||||||
|
if ( m_bInit == true ) |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : Player reset.\n" ); |
||||||
|
|
||||||
|
Stop(); |
||||||
|
|
||||||
|
audiofile_t *p = NULL; |
||||||
|
|
||||||
|
while ( m_pTrack != NULL ) |
||||||
|
{ |
||||||
|
p = m_pTrack; |
||||||
|
m_pTrack = p->next; |
||||||
|
delete p; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CMusic :: Terminate ( void ) //Cleanup and dereference
|
||||||
|
{ |
||||||
|
gEngfuncs.Con_Printf ( "MUSICPLAYER : Terminating and unloading.\n" ); |
||||||
|
ma_device_uninit(&device); |
||||||
|
ma_decoder_uninit(&decoder); |
||||||
|
g_MusicPlayer.m_bInit = false; |
||||||
|
} |
||||||
|
|
||||||
|
#endif //End if #ifndef DISABLE_MINIAUDIO
|
||||||
|
|
||||||
|
/*//---------------
|
||||||
|
Playlist contents |
||||||
|
|
||||||
|
example: music01.txt file: |
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
3 |
||||||
|
|
||||||
|
monmod/sound/mp3/music01_debut.mp3 1 |
||||||
|
monmod/sound/mp3/music01_boucle.mp3 3 |
||||||
|
monmod/sound/mp3/music01_fin.mp3 1 |
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
composition : |
||||||
|
- total number of tracks |
||||||
|
- path of the first music file |
||||||
|
- times to repeat that file |
||||||
|
- path of the second |
||||||
|
- etc ... |
||||||
|
|
||||||
|
*///---------------
|
@ -0,0 +1,97 @@ |
|||||||
|
//-------------------------------------------------------------
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-
|
||||||
|
//- clientmusic.h
|
||||||
|
//-
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//- by Roy at suggestion by nekonomicon, based on code by JujU
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//- mp3 player code for HL mod
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-
|
||||||
|
//- compatible with version 0.11.9 of Miniaudio
|
||||||
|
//- https://github.com/mackron/miniaudio
|
||||||
|
//-
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef CLIENTMUSIC_H |
||||||
|
#define CLIENTMUSIC_H |
||||||
|
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION |
||||||
|
|
||||||
|
#if _WIN32 |
||||||
|
#define HSPRITE WINDOWS_HSPRITE //Apparently miniaudio introduces a win32 conflict here.
|
||||||
|
#endif |
||||||
|
#include "../miniaudio/miniaudio.h" |
||||||
|
#if _WIN32 |
||||||
|
#undef HSPRITE |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// defines
|
||||||
|
|
||||||
|
#define MUSIC_AUDIO_FILE 1 |
||||||
|
#define MUSIC_LIST_FILE 0 |
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// audio file structure
|
||||||
|
|
||||||
|
struct audiofile_t |
||||||
|
{ |
||||||
|
char name [128]; |
||||||
|
int repeat; |
||||||
|
audiofile_t *next; |
||||||
|
}; |
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// reader class
|
||||||
|
|
||||||
|
|
||||||
|
class CMusic //: public CHudBase
|
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
// reading functions
|
||||||
|
|
||||||
|
void OpenFile ( char *filename, int repeat ); // open a single file
|
||||||
|
void OpenList ( char *filename ); // opening a text file containing the files
|
||||||
|
|
||||||
|
void Init ( void ); // initialization
|
||||||
|
|
||||||
|
void Play ( void ); // playback
|
||||||
|
void Stop ( void ); // stop
|
||||||
|
void Reset ( void ); // pause and switch to next track
|
||||||
|
void Terminate ( void ); // clean-up during termination
|
||||||
|
|
||||||
|
// variables
|
||||||
|
|
||||||
|
bool m_IsPlaying; // monitors whether the music is played, used to pause the music
|
||||||
|
bool m_bInit; // checks if the player is initialized
|
||||||
|
|
||||||
|
audiofile_t *m_pTrack; // playlist items
|
||||||
|
|
||||||
|
// constructor / destructor
|
||||||
|
|
||||||
|
CMusic () { m_bInit = false; m_IsPlaying = false; m_pTrack = NULL; Reset(); }; |
||||||
|
~CMusic () { Terminate(); }; |
||||||
|
|
||||||
|
// object instances
|
||||||
|
|
||||||
|
ma_result result; |
||||||
|
ma_decoder decoder; |
||||||
|
ma_device_config deviceConfig; |
||||||
|
ma_device device; |
||||||
|
|
||||||
|
// messages
|
||||||
|
|
||||||
|
int MsgFunc_CMusicOpen ( const char *pszName, int iSize, void *pbuf ); |
||||||
|
|
||||||
|
// monitoring functions
|
||||||
|
|
||||||
|
void songEnd(); |
||||||
|
}; |
||||||
|
|
||||||
|
extern CMusic g_MusicPlayer; |
||||||
|
#endif // CLIENTMUSIC_H
|
@ -1,32 +0,0 @@ |
|||||||
#ifndef _FMOD_ERRORS_H |
|
||||||
#define _FMOD_ERRORS_H |
|
||||||
|
|
||||||
static char *FMOD_ErrorString(int errcode) |
|
||||||
{ |
|
||||||
switch (errcode) |
|
||||||
{ |
|
||||||
case FMOD_ERR_NONE: return "No errors"; |
|
||||||
case FMOD_ERR_BUSY: return "Cannot call this command after FSOUND_Init. Call FSOUND_Close first."; |
|
||||||
case FMOD_ERR_UNINITIALIZED: return "This command failed because FSOUND_Init was not called or called properly"; |
|
||||||
case FMOD_ERR_PLAY: return "Playing the sound failed."; |
|
||||||
case FMOD_ERR_INIT: return "Error initializing output device."; |
|
||||||
case FMOD_ERR_ALLOCATED: return "The output device is already in use and cannot be reused."; |
|
||||||
case FMOD_ERR_OUTPUT_FORMAT: return "Soundcard does not support the features needed for this soundsystem (16bit stereo output)"; |
|
||||||
case FMOD_ERR_COOPERATIVELEVEL: return "Error setting cooperative level for hardware."; |
|
||||||
case FMOD_ERR_CREATEBUFFER: return "Error creating hardware sound buffer."; |
|
||||||
case FMOD_ERR_FILE_NOTFOUND: return "File not found"; |
|
||||||
case FMOD_ERR_FILE_FORMAT: return "Unknown file format"; |
|
||||||
case FMOD_ERR_FILE_BAD: return "Error loading file"; |
|
||||||
case FMOD_ERR_MEMORY: return "Not enough memory "; |
|
||||||
case FMOD_ERR_VERSION: return "The version number of this file format is not supported"; |
|
||||||
case FMOD_ERR_INVALID_PARAM: return "An invalid parameter was passed to this function"; |
|
||||||
case FMOD_ERR_NO_EAX: return "Tried to use an EAX command on a non EAX enabled channel or output."; |
|
||||||
case FMOD_ERR_CHANNEL_ALLOC: return "Failed to allocate a new channel"; |
|
||||||
case FMOD_ERR_RECORD: return "Recording not supported on this device"; |
|
||||||
case FMOD_ERR_MEDIAPLAYER: return "Required Mediaplayer codec is not installed"; |
|
||||||
|
|
||||||
default : return "Unknown error"; |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif |
|
@ -1,73 +0,0 @@ |
|||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- music.h ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- by Roy, based on the code by JujU -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- tee file for null player
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MUSIC_H |
|
||||||
#define MUSIC_H |
|
||||||
|
|
||||||
//Temporary plug to have something to work with on Linux modif de Roy
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// defines
|
|
||||||
|
|
||||||
#define MUSIC_AUDIO_FILE 1 |
|
||||||
#define MUSIC_LIST_FILE 0 |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// structure of the audio file entity
|
|
||||||
|
|
||||||
struct audiofile_t |
|
||||||
{ |
|
||||||
char name [128]; |
|
||||||
int repeat; |
|
||||||
audiofile_t *next; |
|
||||||
}; |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// music class
|
|
||||||
|
|
||||||
|
|
||||||
class CMusic |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
// fonctions de lecture
|
|
||||||
|
|
||||||
void OpenFile ( const char *filename, int repeat ); // ouverture d'un simple fichier
|
|
||||||
void OpenList ( const char *filename ); // ouverture d'un fichier texte contenant les fichiers
|
|
||||||
|
|
||||||
void Init ( void ); // initialisation
|
|
||||||
|
|
||||||
void Play ( void ); // lecture
|
|
||||||
void Stop ( void ); // arr
|
|
||||||
void Reset ( void ); // fermeture
|
|
||||||
|
|
||||||
// variables
|
|
||||||
|
|
||||||
|
|
||||||
int m_fsound; //We don't actually have FMOD, so just an int handle.
|
|
||||||
|
|
||||||
BOOL m_IsPlaying; // t
|
|
||||||
BOOL m_bInit; // t
|
|
||||||
|
|
||||||
audiofile_t *m_pTrack; //current track
|
|
||||||
|
|
||||||
// constructor & destructor
|
|
||||||
|
|
||||||
CMusic () { m_bInit = FALSE; m_IsPlaying = FALSE; m_pTrack = NULL; Reset(); }; |
|
||||||
~CMusic () {}; |
|
||||||
|
|
||||||
// functions import
|
|
||||||
// none, see window / Julien's code.
|
|
||||||
}; |
|
||||||
|
|
||||||
extern CMusic g_MusicPlayer; |
|
||||||
#endif // MUSIC_H
|
|
@ -1,446 +0,0 @@ |
|||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- musicfmod.cpp ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- par JujU -----------
|
|
||||||
//- julien.lecorre@free.fr -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- code du lecteur mp3 pour mod HL -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- compatible avec la version 3.6.1 de fmod.dll ---
|
|
||||||
//- http://www.fmod.org/ ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/*//---------------
|
|
||||||
|
|
||||||
mettre la dll fmod.dll dans le dossier half life. |
|
||||||
|
|
||||||
changer l'adresse de la dll dans le #define FMOD_DLL_PATH |
|
||||||
du fichier .h |
|
||||||
attention, mettre des \\ et pas des \ dans l'adresse. |
|
||||||
|
|
||||||
code |
|
||||||
fin de ce fichier. |
|
||||||
|
|
||||||
composition des fichiers texte listes de fichiers audio : |
|
||||||
voir |
|
||||||
|
|
||||||
*///---------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// inclusions
|
|
||||||
|
|
||||||
#include "extdll.h" |
|
||||||
#include "util.h" |
|
||||||
#include "cbase.h" |
|
||||||
|
|
||||||
#include "musicfmod.h" |
|
||||||
|
|
||||||
CMusic g_MusicPlayer; |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// initialisation
|
|
||||||
|
|
||||||
void CMusic :: Init ( void ) |
|
||||||
{ |
|
||||||
m_hFmodDll = LoadLibrary ( FMOD_DLL_PATH ); |
|
||||||
|
|
||||||
if ( m_hFmodDll == NULL ) |
|
||||||
return; |
|
||||||
|
|
||||||
(FARPROC&)FSOUND_INIT = GetProcAddress(m_hFmodDll, "_FSOUND_Init@12"); |
|
||||||
(FARPROC&)FSOUND_CLOSE = GetProcAddress(m_hFmodDll, "_FSOUND_Close@0"); |
|
||||||
(FARPROC&)FSOUND_STREAM_OPENFILE = GetProcAddress(m_hFmodDll, "_FSOUND_Stream_OpenFile@12"); |
|
||||||
(FARPROC&)FSOUND_STREAM_CLOSE = GetProcAddress(m_hFmodDll, "_FSOUND_Stream_Close@4"); |
|
||||||
(FARPROC&)FSOUND_STREAM_PLAY = GetProcAddress(m_hFmodDll, "_FSOUND_Stream_Play@8"); |
|
||||||
(FARPROC&)FSOUND_STREAM_ENDCALLBACK = GetProcAddress(m_hFmodDll, "_FSOUND_Stream_SetEndCallback@12"); |
|
||||||
|
|
||||||
|
|
||||||
if ( !( FSOUND_INIT && FSOUND_CLOSE && FSOUND_STREAM_OPENFILE && FSOUND_STREAM_CLOSE && FSOUND_STREAM_PLAY && FSOUND_STREAM_ENDCALLBACK )) |
|
||||||
{ |
|
||||||
FreeLibrary( m_hFmodDll ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
if (!FSOUND_INIT(44100, 1, 0)) |
|
||||||
return; |
|
||||||
|
|
||||||
|
|
||||||
m_bInit = TRUE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// lecture d'un fichier audio
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: OpenFile ( const char *filename, int repeat ) |
|
||||||
{ |
|
||||||
audiofile_t *p = NULL; |
|
||||||
p = new audiofile_t; |
|
||||||
|
|
||||||
sprintf ( p->name, filename ); |
|
||||||
p->repeat = repeat; |
|
||||||
p->next = m_pTrack; |
|
||||||
|
|
||||||
m_pTrack = p; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// lecture d'une liste de fichiers audio
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: OpenList ( const char *filename ) |
|
||||||
{ |
|
||||||
|
|
||||||
// ouverture du fichier texte
|
|
||||||
|
|
||||||
FILE *myfile = fopen ( filename, "r" ); |
|
||||||
|
|
||||||
if ( myfile == NULL ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : impossible d'ouvrir %s\n\\\n", filename ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// enregistrement des morceaux dans la liste
|
|
||||||
|
|
||||||
int total = 0; |
|
||||||
|
|
||||||
if ( fscanf ( myfile, "%i", &total ) != EOF ) |
|
||||||
{ |
|
||||||
for ( int i=0; i<total; i++ ) |
|
||||||
{ |
|
||||||
char ctitle [128]; |
|
||||||
int irepeat; |
|
||||||
|
|
||||||
// lecture du titre
|
|
||||||
|
|
||||||
if ( fscanf ( myfile, "%s", ctitle ) != EOF ) |
|
||||||
{ |
|
||||||
if ( fscanf ( myfile, "%i", &irepeat ) != EOF ) |
|
||||||
OpenFile ( ctitle, irepeat ); |
|
||||||
|
|
||||||
else |
|
||||||
break; |
|
||||||
} |
|
||||||
else |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// fermeture du fichier texte
|
|
||||||
|
|
||||||
fclose ( myfile ); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// fin du morceau
|
|
||||||
|
|
||||||
|
|
||||||
signed char EndCallback ( FSOUND_STREAM *stream, void *buff, int len, int param ) |
|
||||||
{ |
|
||||||
// fin du morceau
|
|
||||||
|
|
||||||
g_MusicPlayer.Stop (); |
|
||||||
|
|
||||||
// recherche du premier morceau de la liste
|
|
||||||
|
|
||||||
audiofile_t *p = NULL; |
|
||||||
p = g_MusicPlayer.m_pTrack; |
|
||||||
|
|
||||||
while ( p != NULL ) |
|
||||||
{ |
|
||||||
if ( p->next == NULL ) |
|
||||||
break; |
|
||||||
else |
|
||||||
p = p->next; |
|
||||||
} |
|
||||||
|
|
||||||
if ( p == NULL ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : aucun morceau dans la liste\n\\\n" ); |
|
||||||
return TRUE; |
|
||||||
} |
|
||||||
|
|
||||||
// d
|
|
||||||
|
|
||||||
p->repeat --; |
|
||||||
|
|
||||||
// suppression des morceaux dont la r
|
|
||||||
|
|
||||||
if ( p->repeat < 1 ) |
|
||||||
{ |
|
||||||
if ( g_MusicPlayer.m_pTrack == p ) |
|
||||||
{ |
|
||||||
delete g_MusicPlayer.m_pTrack; |
|
||||||
g_MusicPlayer.m_pTrack = NULL; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
audiofile_t *q = NULL; |
|
||||||
q = g_MusicPlayer.m_pTrack; |
|
||||||
|
|
||||||
while ( q->next != p ) |
|
||||||
q = q->next; |
|
||||||
|
|
||||||
delete q->next; |
|
||||||
q->next = NULL; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// fermeture du lecteur si la liste est vide
|
|
||||||
|
|
||||||
if ( g_MusicPlayer.m_pTrack == NULL ) |
|
||||||
{ |
|
||||||
g_MusicPlayer.Reset (); |
|
||||||
} |
|
||||||
|
|
||||||
// lancement du morceau suivant
|
|
||||||
|
|
||||||
else |
|
||||||
{ |
|
||||||
g_MusicPlayer.Play(); |
|
||||||
} |
|
||||||
|
|
||||||
return TRUE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// lecture
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: Play ( void ) |
|
||||||
{ |
|
||||||
if ( m_IsPlaying == TRUE ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( m_bInit == FALSE ) |
|
||||||
{ |
|
||||||
Init (); |
|
||||||
|
|
||||||
if ( m_bInit == FALSE ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : initialisation impossible\n\\\n" ); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// recherche du premier morceau de la liste
|
|
||||||
|
|
||||||
audiofile_t *p = NULL; |
|
||||||
p = m_pTrack; |
|
||||||
|
|
||||||
while ( p != NULL ) |
|
||||||
{ |
|
||||||
if ( p->next == NULL ) |
|
||||||
break; |
|
||||||
else |
|
||||||
p = p->next; |
|
||||||
} |
|
||||||
|
|
||||||
if ( p == NULL ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : aucun morceau dans la liste\n\\\n" ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// chargement du fichier
|
|
||||||
|
|
||||||
m_fsound = FSOUND_STREAM_OPENFILE( p->name, FSOUND_NORMAL | FSOUND_LOOP_OFF, 0 ); |
|
||||||
|
|
||||||
if (!m_fsound) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : %s : fichier introuvable\n\\\n", p->name ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// lecture
|
|
||||||
|
|
||||||
FSOUND_STREAM_PLAY ( FSOUND_FREE, m_fsound ); |
|
||||||
m_IsPlaying = TRUE; |
|
||||||
|
|
||||||
// callback en fin de morceau
|
|
||||||
|
|
||||||
FSOUND_STREAM_ENDCALLBACK ( m_fsound, EndCallback, 0 ); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: Stop ( void ) |
|
||||||
{ |
|
||||||
if ( m_IsPlaying == TRUE ) |
|
||||||
{ |
|
||||||
m_IsPlaying = FALSE; |
|
||||||
FSOUND_STREAM_CLOSE ( m_fsound ); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: Reset ( void ) |
|
||||||
{ |
|
||||||
//r
|
|
||||||
|
|
||||||
Stop (); |
|
||||||
|
|
||||||
audiofile_t *p = NULL; |
|
||||||
|
|
||||||
while ( m_pTrack != NULL ) |
|
||||||
{ |
|
||||||
p = m_pTrack; |
|
||||||
m_pTrack = p->next; |
|
||||||
delete p; |
|
||||||
} |
|
||||||
|
|
||||||
if ( m_bInit == TRUE ) |
|
||||||
{ |
|
||||||
FSOUND_CLOSE(); |
|
||||||
g_MusicPlayer.m_bInit = FALSE; |
|
||||||
|
|
||||||
// FreeLibrary( g_MusicPlayer.m_hFmodDll );
|
|
||||||
g_MusicPlayer.m_hFmodDll = NULL; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// classe de l'entit
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CTriggerMusic : public CPointEntity |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
void Spawn ( void ); |
|
||||||
|
|
||||||
void KeyValue ( KeyValueData *pkvd ); |
|
||||||
void Use ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
||||||
|
|
||||||
|
|
||||||
virtual int Save ( CSave &save ); |
|
||||||
virtual int Restore ( CRestore &restore ); |
|
||||||
|
|
||||||
static TYPEDESCRIPTION m_SaveData[]; |
|
||||||
|
|
||||||
|
|
||||||
string_t m_iFileName; // chemin du fichier
|
|
||||||
int m_iFileType; // fichier texte ( liste ) ou fichier audio
|
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
LINK_ENTITY_TO_CLASS( trigger_music, CTriggerMusic ); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TYPEDESCRIPTION CTriggerMusic::m_SaveData[] = |
|
||||||
{ |
|
||||||
DEFINE_FIELD( CTriggerMusic, m_iFileType, FIELD_INTEGER ), |
|
||||||
DEFINE_FIELD( CTriggerMusic, m_iFileName, FIELD_STRING ), |
|
||||||
}; |
|
||||||
|
|
||||||
IMPLEMENT_SAVERESTORE( CTriggerMusic, CPointEntity ); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CTriggerMusic :: Spawn( void ) |
|
||||||
{ |
|
||||||
pev->solid = SOLID_NOT; |
|
||||||
pev->effects = EF_NODRAW; |
|
||||||
} |
|
||||||
|
|
||||||
void CTriggerMusic :: KeyValue( KeyValueData *pkvd ) |
|
||||||
{ |
|
||||||
if (FStrEq(pkvd->szKeyName, "filetype")) |
|
||||||
{ |
|
||||||
m_iFileType = atoi(pkvd->szValue); |
|
||||||
pkvd->fHandled = TRUE; |
|
||||||
} |
|
||||||
else if (FStrEq(pkvd->szKeyName, "filename")) |
|
||||||
{ |
|
||||||
m_iFileName = ALLOC_STRING(pkvd->szValue); |
|
||||||
pkvd->fHandled = TRUE; |
|
||||||
} |
|
||||||
else |
|
||||||
CPointEntity::KeyValue( pkvd ); |
|
||||||
} |
|
||||||
|
|
||||||
void CTriggerMusic :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
||||||
{ |
|
||||||
if ( g_MusicPlayer.m_IsPlaying == TRUE ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( m_iFileType == MUSIC_AUDIO_FILE ) |
|
||||||
{ |
|
||||||
g_MusicPlayer.OpenFile ( STRING(m_iFileName), 1 ); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
g_MusicPlayer.OpenList ( STRING(m_iFileName) ); |
|
||||||
} |
|
||||||
|
|
||||||
g_MusicPlayer.Play(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*//---------------
|
|
||||||
code |
|
||||||
|
|
||||||
|
|
||||||
@PointClass base( Targetname ) = trigger_music : "Trigger Music" |
|
||||||
[ |
|
||||||
filetype(choices) : "Type de fichier" : 0 = |
|
||||||
[ |
|
||||||
0: "Liste de fichiers (*.txt)" |
|
||||||
1: "Fichier wav mp2 mp3 ogg raw" |
|
||||||
] |
|
||||||
filename(string) : "Nom (mod/dossier/fichier.extension)" |
|
||||||
] |
|
||||||
|
|
||||||
*///---------------
|
|
||||||
|
|
||||||
|
|
||||||
/*//---------------
|
|
||||||
composition des listes de fichiers audio |
|
||||||
|
|
||||||
exemple : fichier music01.txt : |
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
3 |
|
||||||
|
|
||||||
monmod/sound/mp3/music01_debut.mp3 1 |
|
||||||
monmod/sound/mp3/music01_boucle.mp3 3 |
|
||||||
monmod/sound/mp3/music01_fin.mp3 1 |
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
composition : |
|
||||||
- nombre total de morceaux diff |
|
||||||
- adresse du premier fichier musique |
|
||||||
- nombre de lectures de ce fichier |
|
||||||
- adresse du deuxi |
|
||||||
- etc ... |
|
||||||
|
|
||||||
*///---------------
|
|
@ -1,94 +0,0 @@ |
|||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- musicfmod.h ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- par JujU -----------
|
|
||||||
//- julien.lecorre@free.fr -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- fichier d'en t
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- compatible avec la version 3.6.1 de fmod.dll ---
|
|
||||||
//- http://www.fmod.org/ ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MUSIC_H |
|
||||||
#define MUSIC_H |
|
||||||
|
|
||||||
#include <fmod.h> |
|
||||||
#include <windows.h> |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// defines
|
|
||||||
|
|
||||||
#define MUSIC_AUDIO_FILE 1 |
|
||||||
#define MUSIC_LIST_FILE 0 |
|
||||||
|
|
||||||
#define FMOD_DLL_PATH "invasion\\fmod.dll" |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// structure fichier audio
|
|
||||||
|
|
||||||
struct audiofile_t |
|
||||||
{ |
|
||||||
char name [128]; |
|
||||||
int repeat; |
|
||||||
audiofile_t *next; |
|
||||||
}; |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// classe du lecteur
|
|
||||||
|
|
||||||
|
|
||||||
class CMusic |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
// fonctions de lecture
|
|
||||||
|
|
||||||
void OpenFile ( const char *filename, int repeat ); // ouverture d'un simple fichier
|
|
||||||
void OpenList ( const char *filename ); // ouverture d'un fichier texte contenant les fichiers
|
|
||||||
|
|
||||||
void Init ( void ); // initialisation
|
|
||||||
|
|
||||||
void Play ( void ); // lecture
|
|
||||||
void Stop ( void ); // arr
|
|
||||||
void Reset ( void ); // fermeture
|
|
||||||
|
|
||||||
// variables
|
|
||||||
|
|
||||||
FSOUND_STREAM *m_fsound; // handle du fichier en cours de lecture
|
|
||||||
|
|
||||||
BOOL m_IsPlaying; // t
|
|
||||||
BOOL m_bInit; // t
|
|
||||||
|
|
||||||
audiofile_t *m_pTrack; // morceaux
|
|
||||||
|
|
||||||
// constructeur / destructeur
|
|
||||||
|
|
||||||
CMusic () { m_bInit = FALSE; m_IsPlaying = FALSE; m_pTrack = NULL; Reset(); }; |
|
||||||
~CMusic () {}; |
|
||||||
|
|
||||||
// fonctions import
|
|
||||||
|
|
||||||
signed char (_stdcall * FSOUND_INIT ) (int mixrate, int maxsoftwarechannels, unsigned int flags); |
|
||||||
void (_stdcall * FSOUND_CLOSE ) (void); |
|
||||||
FSOUND_STREAM * (_stdcall * FSOUND_STREAM_OPENFILE ) (const char *filename, unsigned int mode, int memlength); |
|
||||||
signed char (_stdcall * FSOUND_STREAM_CLOSE ) (FSOUND_STREAM *stream); |
|
||||||
int (_stdcall * FSOUND_STREAM_PLAY ) (int channel, FSOUND_STREAM *stream); |
|
||||||
signed char (_stdcall * FSOUND_STREAM_ENDCALLBACK) (FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, int userdata); |
|
||||||
|
|
||||||
HINSTANCE m_hFmodDll; |
|
||||||
}; |
|
||||||
|
|
||||||
extern CMusic g_MusicPlayer; |
|
||||||
|
|
||||||
#endif // MUSIC_H
|
|
@ -1,511 +0,0 @@ |
|||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- musicgstreamer.cpp ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- by Roy, based on the code by JujU -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- mp3 player code for HL mod -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- compatible with version 1.0 of Gstreamer ---
|
|
||||||
//- http://www.gstreamer.freedesktop.org/ ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/*//---------------
|
|
||||||
|
|
||||||
Don't forget to link the actual library to GStreamer. |
|
||||||
|
|
||||||
GStreamer 1.0 or better required. |
|
||||||
|
|
||||||
Tested |
|
||||||
with 32-bit GStreamer on Debian |
|
||||||
|
|
||||||
For playlist format: |
|
||||||
see the bottom of the file |
|
||||||
|
|
||||||
*///---------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// inclusions
|
|
||||||
|
|
||||||
#include "extdll.h" |
|
||||||
#include "util.h" |
|
||||||
#include "cbase.h" |
|
||||||
|
|
||||||
#include "musicgstreamer.h" |
|
||||||
|
|
||||||
CMusic g_MusicPlayer; |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// initialisation
|
|
||||||
|
|
||||||
void CMusic :: Init ( void ) |
|
||||||
{ |
|
||||||
int argc = 0; |
|
||||||
char** argv = nullptr; |
|
||||||
GError *error = nullptr; |
|
||||||
|
|
||||||
if( m_bInit == TRUE ){ |
|
||||||
return; //Do not re-init.
|
|
||||||
} |
|
||||||
|
|
||||||
if (gst_init_check(&argc,&argv,&error)!=TRUE) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : unable to initialize\n\\\n" ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
m_bInit = TRUE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// monitoring the bus
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: updateBus ( ) |
|
||||||
{ |
|
||||||
if(gstBus == NULL) return; //Do not react if bus doesn't exist.
|
|
||||||
gstMsg = gst_bus_pop (gstBus); |
|
||||||
if(gstMsg != NULL){ |
|
||||||
if (GST_MESSAGE_TYPE (gstMsg) == GST_MESSAGE_ERROR) { |
|
||||||
ALERT( at_console, "\\\nMUSICPLAYER : A GStreamer error has occured.\n\\\n" ); |
|
||||||
}else if (GST_MESSAGE_TYPE (gstMsg) == GST_MESSAGE_EOS) { |
|
||||||
ALERT( at_console, "\\\nMUSICPLAYER : A song has ended.\n\\\n" ); |
|
||||||
songEnd(); |
|
||||||
} |
|
||||||
} |
|
||||||
if(gstMsg != NULL) gst_message_unref (gstMsg); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// playing an audio file
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: OpenFile ( const char *filename, int repeat ) |
|
||||||
{ |
|
||||||
audiofile_t *p = NULL; |
|
||||||
p = new audiofile_t; |
|
||||||
|
|
||||||
sprintf ( p->name, filename ); |
|
||||||
p->repeat = repeat; |
|
||||||
p->next = m_pTrack; |
|
||||||
|
|
||||||
m_pTrack = p; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// play a list of audio files
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: OpenList ( const char *filename ) |
|
||||||
{ |
|
||||||
|
|
||||||
// open text file
|
|
||||||
|
|
||||||
FILE *myfile = fopen ( filename, "r" ); |
|
||||||
|
|
||||||
if ( myfile == NULL ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : impossible to load %s\n\\\n", filename ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// saving songs to the list
|
|
||||||
|
|
||||||
int total = 0; |
|
||||||
|
|
||||||
if ( fscanf ( myfile, "%i", &total ) != EOF ) |
|
||||||
{ |
|
||||||
for ( int i=0; i<total; i++ ) |
|
||||||
{ |
|
||||||
char ctitle [128]; |
|
||||||
int irepeat; |
|
||||||
|
|
||||||
// reading the title
|
|
||||||
|
|
||||||
if ( fscanf ( myfile, "%s", ctitle ) != EOF ) |
|
||||||
{ |
|
||||||
if ( fscanf ( myfile, "%i", &irepeat ) != EOF ) |
|
||||||
OpenFile ( ctitle, irepeat ); |
|
||||||
|
|
||||||
else |
|
||||||
break; |
|
||||||
} |
|
||||||
else |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// close text file
|
|
||||||
|
|
||||||
fclose ( myfile ); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// end of the song
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: songEnd ( ) |
|
||||||
{ |
|
||||||
// end of the song
|
|
||||||
|
|
||||||
g_MusicPlayer.Stop (); |
|
||||||
|
|
||||||
// search for the first song in the list
|
|
||||||
|
|
||||||
audiofile_t *p = NULL; |
|
||||||
p = g_MusicPlayer.m_pTrack; |
|
||||||
|
|
||||||
while ( p != NULL ) |
|
||||||
{ |
|
||||||
if ( p->next == NULL ) |
|
||||||
break; |
|
||||||
else |
|
||||||
p = p->next; |
|
||||||
} |
|
||||||
|
|
||||||
if ( p == NULL ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : no song in the list\n\\\n" ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// d
|
|
||||||
|
|
||||||
p->repeat --; |
|
||||||
|
|
||||||
// removal of songs whose r
|
|
||||||
|
|
||||||
if ( p->repeat < 1 ) |
|
||||||
{ |
|
||||||
if ( g_MusicPlayer.m_pTrack == p ) |
|
||||||
{ |
|
||||||
delete g_MusicPlayer.m_pTrack; |
|
||||||
g_MusicPlayer.m_pTrack = NULL; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
audiofile_t *q = NULL; |
|
||||||
q = g_MusicPlayer.m_pTrack; |
|
||||||
|
|
||||||
while ( q->next != p ) |
|
||||||
q = q->next; |
|
||||||
|
|
||||||
delete q->next; |
|
||||||
q->next = NULL; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// close player if list is empty
|
|
||||||
|
|
||||||
if ( g_MusicPlayer.m_pTrack == NULL ) |
|
||||||
{ |
|
||||||
g_MusicPlayer.Reset (); |
|
||||||
} |
|
||||||
|
|
||||||
// next track start
|
|
||||||
|
|
||||||
else |
|
||||||
{ |
|
||||||
g_MusicPlayer.Play(); |
|
||||||
} |
|
||||||
|
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// instruction
|
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: Play ( void ) |
|
||||||
{ |
|
||||||
if ( m_IsPlaying == TRUE ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( m_bInit == FALSE ) |
|
||||||
{ |
|
||||||
Init (); |
|
||||||
|
|
||||||
if ( m_bInit == FALSE ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : unable to initialize\n\\\n" ); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// search for the first song in the list
|
|
||||||
|
|
||||||
audiofile_t *p = NULL; |
|
||||||
p = m_pTrack; |
|
||||||
|
|
||||||
while ( p != NULL ) |
|
||||||
{ |
|
||||||
if ( p->next == NULL ) |
|
||||||
break; |
|
||||||
else |
|
||||||
p = p->next; |
|
||||||
} |
|
||||||
|
|
||||||
if ( p == NULL ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : no song in the list\n\\\n" ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
//Stop previous pipeline activity
|
|
||||||
if (gstPipeline != NULL){ |
|
||||||
gst_element_set_state (gstPipeline, GST_STATE_NULL); |
|
||||||
gst_object_unref (gstPipeline); |
|
||||||
gstPipeline = NULL; |
|
||||||
} |
|
||||||
if (gstBus != NULL){ |
|
||||||
gst_object_unref (gstBus); |
|
||||||
gstBus = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
// loading file
|
|
||||||
char pipelinePayload [512]; |
|
||||||
sprintf(pipelinePayload, "filesrc location=%s ! decodebin ! audioconvert ! audioresample ! autoaudiosink", p->name); |
|
||||||
gstPipeline = gst_parse_launch(pipelinePayload, NULL); |
|
||||||
|
|
||||||
|
|
||||||
if (gstPipeline == NULL) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : %s : can not start playing the file\n\\\n", p->name ); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// playback
|
|
||||||
|
|
||||||
gst_element_set_state (gstPipeline, GST_STATE_PLAYING); |
|
||||||
m_IsPlaying = TRUE; |
|
||||||
|
|
||||||
// callback at the end of the song
|
|
||||||
|
|
||||||
gstBus = gst_element_get_bus (gstPipeline); //Get bus to monitor
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: Stop ( void ) |
|
||||||
{ |
|
||||||
if ( m_IsPlaying == TRUE ) |
|
||||||
{ |
|
||||||
m_IsPlaying = FALSE; |
|
||||||
if (gstPipeline != NULL){ |
|
||||||
gst_element_set_state (gstPipeline, GST_STATE_READY); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void CMusic :: Reset ( void ) |
|
||||||
{ |
|
||||||
//r
|
|
||||||
|
|
||||||
Stop (); |
|
||||||
|
|
||||||
audiofile_t *p = NULL; |
|
||||||
|
|
||||||
while ( m_pTrack != NULL ) |
|
||||||
{ |
|
||||||
p = m_pTrack; |
|
||||||
m_pTrack = p->next; |
|
||||||
delete p; |
|
||||||
} |
|
||||||
|
|
||||||
if ( m_bInit == TRUE ) |
|
||||||
{ |
|
||||||
if (gstPipeline != NULL){ |
|
||||||
gst_element_set_state (gstPipeline, GST_STATE_NULL); |
|
||||||
gst_object_unref (gstPipeline); |
|
||||||
gstPipeline = NULL; |
|
||||||
} |
|
||||||
if (gstBus != NULL){ |
|
||||||
gst_object_unref (gstBus); |
|
||||||
gstBus = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
//complete
|
|
||||||
//we don't actually de-initialize gst here
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CMusic :: Terminate ( void ) //Cleanup and dereference
|
|
||||||
{ |
|
||||||
Stop (); |
|
||||||
if ( m_bInit == TRUE ) |
|
||||||
{ |
|
||||||
ALERT ( at_console, "\\\nMUSICPLAYER : de-initializing and dereferencing\n\\\n" ); |
|
||||||
if (gstPipeline != NULL){ |
|
||||||
gst_element_set_state (gstPipeline, GST_STATE_NULL); |
|
||||||
gst_object_unref (gstPipeline); |
|
||||||
gstPipeline = NULL; |
|
||||||
} |
|
||||||
if (gstBus != NULL){ |
|
||||||
gst_object_unref (gstBus); |
|
||||||
gstBus = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
gst_deinit (); |
|
||||||
g_MusicPlayer.m_bInit = FALSE; //Neither.
|
|
||||||
|
|
||||||
//complete
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// entity class
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CTriggerMusic : public CPointEntity |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
void Spawn ( void ); |
|
||||||
|
|
||||||
void KeyValue ( KeyValueData *pkvd ); |
|
||||||
void Use ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
||||||
|
|
||||||
void EXPORT Think( void ); |
|
||||||
|
|
||||||
virtual int Save ( CSave &save ); |
|
||||||
virtual int Restore ( CRestore &restore ); |
|
||||||
|
|
||||||
|
|
||||||
static TYPEDESCRIPTION m_SaveData[]; |
|
||||||
|
|
||||||
|
|
||||||
string_t m_iFileName; // file path
|
|
||||||
int m_iFileType; // text file (list) or audio file
|
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
LINK_ENTITY_TO_CLASS( trigger_music, CTriggerMusic ); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TYPEDESCRIPTION CTriggerMusic::m_SaveData[] = |
|
||||||
{ |
|
||||||
DEFINE_FIELD( CTriggerMusic, m_iFileType, FIELD_INTEGER ), |
|
||||||
DEFINE_FIELD( CTriggerMusic, m_iFileName, FIELD_STRING ), |
|
||||||
}; |
|
||||||
|
|
||||||
IMPLEMENT_SAVERESTORE( CTriggerMusic, CPointEntity ); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CTriggerMusic :: Spawn( void ) |
|
||||||
{ |
|
||||||
pev->solid = SOLID_NOT; |
|
||||||
pev->effects = EF_NODRAW; |
|
||||||
|
|
||||||
SetThink( &CTriggerMusic::Think ); |
|
||||||
pev->nextthink = gpGlobals->time; |
|
||||||
} |
|
||||||
|
|
||||||
void CTriggerMusic::Think( void ) //We need to monitor gst message bus for updates
|
|
||||||
{ |
|
||||||
//if(g_MusicPlayer == NULL) return;
|
|
||||||
g_MusicPlayer.updateBus(); |
|
||||||
pev->nextthink = gpGlobals->time + 0.25f; // Think again in 1/4 second
|
|
||||||
} |
|
||||||
|
|
||||||
void CTriggerMusic :: KeyValue( KeyValueData *pkvd ) |
|
||||||
{ |
|
||||||
if (FStrEq(pkvd->szKeyName, "filetype")) |
|
||||||
{ |
|
||||||
m_iFileType = atoi(pkvd->szValue); |
|
||||||
pkvd->fHandled = TRUE; |
|
||||||
} |
|
||||||
else if (FStrEq(pkvd->szKeyName, "filename")) |
|
||||||
{ |
|
||||||
m_iFileName = ALLOC_STRING(pkvd->szValue); |
|
||||||
pkvd->fHandled = TRUE; |
|
||||||
} |
|
||||||
else |
|
||||||
CPointEntity::KeyValue( pkvd ); |
|
||||||
} |
|
||||||
|
|
||||||
void CTriggerMusic :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
||||||
{ |
|
||||||
if ( g_MusicPlayer.m_IsPlaying == TRUE ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( m_iFileType == MUSIC_AUDIO_FILE ) |
|
||||||
{ |
|
||||||
g_MusicPlayer.OpenFile ( STRING(m_iFileName), 1 ); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
g_MusicPlayer.OpenList ( STRING(m_iFileName) ); |
|
||||||
} |
|
||||||
|
|
||||||
g_MusicPlayer.Play(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*//---------------
|
|
||||||
code |
|
||||||
|
|
||||||
|
|
||||||
@PointClass base( Targetname ) = trigger_music : "Trigger Music" |
|
||||||
[ |
|
||||||
filetype(choices) : "File type" : 0 = |
|
||||||
[ |
|
||||||
0: "File list (*.txt)" |
|
||||||
1: "File wav mp2 mp3 ogg raw" |
|
||||||
] |
|
||||||
filename(string) : "Name (mod/folder/file.extension)" |
|
||||||
] |
|
||||||
|
|
||||||
*///---------------
|
|
||||||
|
|
||||||
|
|
||||||
/*//---------------
|
|
||||||
composing lists of audio files |
|
||||||
|
|
||||||
example: music01.txt file: |
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
3 |
|
||||||
|
|
||||||
monmod/sound/mp3/music01_debut.mp3 1 |
|
||||||
monmod/sound/mp3/music01_boucle.mp3 3 |
|
||||||
monmod/sound/mp3/music01_fin.mp3 1 |
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
composition : |
|
||||||
- total number of diff chunks |
|
||||||
- address of the first music file |
|
||||||
- number of readings of this file |
|
||||||
- address of the second |
|
||||||
- etc ... |
|
||||||
|
|
||||||
*///---------------
|
|
@ -1,85 +0,0 @@ |
|||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- musicgstreamer.h ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- by Roy, based on the code by JujU -----------
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- tee file
|
|
||||||
//---------------------------------------------------------
|
|
||||||
//- ---
|
|
||||||
//- compatible with version 1.0 of Gstreamer ---
|
|
||||||
//- http://www.gstreamer.freedesktop.org/ ---
|
|
||||||
//- ---
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MUSIC_H |
|
||||||
#define MUSIC_H |
|
||||||
|
|
||||||
#include <gst/gst.h> |
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// defines
|
|
||||||
|
|
||||||
#define MUSIC_AUDIO_FILE 1 |
|
||||||
#define MUSIC_LIST_FILE 0 |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// audio file structure
|
|
||||||
|
|
||||||
struct audiofile_t |
|
||||||
{ |
|
||||||
char name [128]; |
|
||||||
int repeat; |
|
||||||
audiofile_t *next; |
|
||||||
}; |
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// reader class
|
|
||||||
|
|
||||||
|
|
||||||
class CMusic |
|
||||||
{ |
|
||||||
public: |
|
||||||
|
|
||||||
// reading functions
|
|
||||||
|
|
||||||
void OpenFile ( const char *filename, int repeat ); // open a single file
|
|
||||||
void OpenList ( const char *filename ); // opening a text file containing the files
|
|
||||||
|
|
||||||
void Init ( void ); // initialization
|
|
||||||
|
|
||||||
void Play ( void ); // playback
|
|
||||||
void Stop ( void ); // stop
|
|
||||||
void Reset ( void ); // closing, but not really
|
|
||||||
void Terminate ( void ); // actually closing
|
|
||||||
|
|
||||||
// variables
|
|
||||||
|
|
||||||
BOOL m_IsPlaying; // t
|
|
||||||
BOOL m_bInit; // t
|
|
||||||
|
|
||||||
audiofile_t *m_pTrack; // parts
|
|
||||||
|
|
||||||
// constructor / destructor
|
|
||||||
|
|
||||||
CMusic () { m_bInit = FALSE; m_IsPlaying = FALSE; m_pTrack = NULL; Reset(); }; |
|
||||||
~CMusic () { Terminate(); }; |
|
||||||
|
|
||||||
// import functions
|
|
||||||
|
|
||||||
GstElement *gstPipeline; |
|
||||||
GstBus *gstBus; |
|
||||||
GstMessage *gstMsg; |
|
||||||
|
|
||||||
void updateBus(); |
|
||||||
void songEnd(); |
|
||||||
}; |
|
||||||
|
|
||||||
extern CMusic g_MusicPlayer; |
|
||||||
#endif // MUSIC_H
|
|
Loading…
Reference in new issue