mirror of
https://github.com/YGGverse/hlsdk-portable.git
synced 2025-08-29 15:22:10 +00:00
HL:Invasion Add MiniAudio Music implementation
This commit is contained in:
parent
e0400761b9
commit
f080ec41b1
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -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
|
||||||
|
@ -49,6 +49,7 @@ option(BUILD_CLIENT "Build client dll" ON)
|
|||||||
option(BUILD_SERVER "Build server dll" ON)
|
option(BUILD_SERVER "Build server dll" ON)
|
||||||
option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" OFF)
|
option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" OFF)
|
||||||
option(USE_GSTREAMER "Enable GStreamer." OFF)
|
option(USE_GSTREAMER "Enable GStreamer." OFF)
|
||||||
|
option(USE_MINIAUDIO "Enable Miniaudio." OFF)
|
||||||
option(USE_FMOD "Enable FMOD." OFF)
|
option(USE_FMOD "Enable FMOD." OFF)
|
||||||
|
|
||||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR
|
if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR
|
||||||
|
32
README.md
32
README.md
@ -47,7 +47,7 @@ Things fixed while transferring code:
|
|||||||
- Sniper rifle zoom states didn't work, m_pPlayer->pev->fov needed to be equalized to m_pPlayer->m_iFOV.
|
- Sniper rifle zoom states didn't work, m_pPlayer->pev->fov needed to be equalized to m_pPlayer->m_iFOV.
|
||||||
- VGUI used to hard-crash, partially fixed: CImageLables in vgui_OrdiControl that caused the crash were replaced with CommandButtons, skipTime added to keypad, OrdiMenu and OrdiControl in order to fix double mouse key presses, +1 added to radiomsg.cpp to fix the butts of the text messages, HUD health display didn't work due to Health Msg system receieving Battery-related data, fixed by manually re-coping a part of old code and paritioning it properly.
|
- VGUI used to hard-crash, partially fixed: CImageLables in vgui_OrdiControl that caused the crash were replaced with CommandButtons, skipTime added to keypad, OrdiMenu and OrdiControl in order to fix double mouse key presses, +1 added to radiomsg.cpp to fix the butts of the text messages, HUD health display didn't work due to Health Msg system receieving Battery-related data, fixed by manually re-coping a part of old code and paritioning it properly.
|
||||||
- Also fixed .txt files and fonts not loading due to backslashes, VGUI folder name being written in capitals and such.
|
- Also fixed .txt files and fonts not loading due to backslashes, VGUI folder name being written in capitals and such.
|
||||||
- Music not playing fixed by creating a GStreamer implementation.
|
- Music not playing fixed by creating Miniaudio (thanks @nekonomicon) and GStreamer implementations.
|
||||||
- l2m3 has a green exploding tank, which has func_door's named tremble_1 and tremble_2, when activated they cause SegFault on any non GoldSource-compatible build. Don't know why yet. Fixed by replacing a multi-manager target with garbage names if the map name and targetname match, see triggers.cpp.
|
- l2m3 has a green exploding tank, which has func_door's named tremble_1 and tremble_2, when activated they cause SegFault on any non GoldSource-compatible build. Don't know why yet. Fixed by replacing a multi-manager target with garbage names if the map name and targetname match, see triggers.cpp.
|
||||||
- Tank used to have a weird sound (glock event playback) when primary attack is activated, fixed with m_iPlayerInTankExternal see hud_tank.cpp and hl_weapons.cpp.
|
- Tank used to have a weird sound (glock event playback) when primary attack is activated, fixed with m_iPlayerInTankExternal see hud_tank.cpp and hl_weapons.cpp.
|
||||||
- IR gun didn't actually Infra-Red anything, fixed by transferring changes to StudioModelRenderer.cpp.
|
- IR gun didn't actually Infra-Red anything, fixed by transferring changes to StudioModelRenderer.cpp.
|
||||||
@ -78,25 +78,33 @@ systems - you're more than welcome to do so!
|
|||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ../ -DUSE_VGUI=1 -DUSE_GSTREAMER=1
|
cmake ../ -DUSE_VGUI=1 -DUSE_MINIAUDIO=1
|
||||||
make
|
make
|
||||||
|
|
||||||
On Debian, the following is necessary to:
|
Must be built with -DUSE_VGUI=1 to work properly, as this mod makes heavy use of true-VGUI, thus update the modules when clonning.
|
||||||
|
|
||||||
|
To be able to hear music during gameplay, on the following three is necessary:
|
||||||
|
-DUSE_MINIAUDIO=1 (this is the smallest and most compatible implementation as of now),
|
||||||
|
-DUSE_GSTREAMER=1 (and have appropriate architechture (i386) gstreamer-1.0 and dev packages installed), or,
|
||||||
|
-DUSE_FMOD=1 (untested, on Windows and will require fmod headers v 3.6.1 if you can still get them somewhere).
|
||||||
|
|
||||||
|
If using MiniAudio, make sure the submodules are updated.
|
||||||
|
As mentioned above, you have to do it anyway to get the VGUI headers.
|
||||||
|
|
||||||
|
If GStreamer is preferred, on Debian, the following is necessary to:
|
||||||
|
|
||||||
sudo apt install libgstreamer1.0:i386 #to play with music (also install plugins)
|
sudo apt install libgstreamer1.0:i386 #to play with music (also install plugins)
|
||||||
sudo apt install libgstreamer1.0-dev:i386 #to compile with music (-DUSE_GSTREAMER=1)
|
sudo apt install libgstreamer1.0-dev:i386 #to compile with music
|
||||||
|
|
||||||
Also added -DUSE_FMOD option for cmake and tried my best to prevent it being used in Linux (uses windows.h include).
|
So far GStreamer should only compile on Linux, as I haven't tested it (or linking it) on any other system.
|
||||||
|
Also, dlls/CMakeLists.txt must have a system-appropriate path to i386 version of GStreamer headers.
|
||||||
|
See set for ```ENV{PKG_CONFIG_PATH}```.
|
||||||
|
|
||||||
|
The FMod option can be used on Windows instead (uses windows.h include),
|
||||||
|
but requires and old and outdated FMod implementation v 3.6.1. Not recommended.
|
||||||
|
|
||||||
The following will likely be necessary to compile a gold-source compatible (old xash, e.t.c) binaries:
|
The following will likely be necessary to compile a gold-source compatible (old xash, e.t.c) binaries:
|
||||||
|
|
||||||
sudo apt install libsdl2-dev:i386
|
sudo apt install libsdl2-dev:i386
|
||||||
|
|
||||||
(but this wants to install a ton of i386 dev packages)
|
(but this wants to install a ton of i386 dev packages)
|
||||||
|
|
||||||
Must be built with -DUSE_VGUI=1 at least to work properly (thus, update the modules when clonning).
|
|
||||||
Must be built with either -DUSE_FMOD=1 (untested, on Windows and will require fmod headers v 3.6.1 if you can still get them somewhere),
|
|
||||||
or -DUSE_GSTREAMER=1 (and have appropriate architechture (i386) gstreamer-1.0 and dev packages installed) to be able to play with music.
|
|
||||||
So far GStreamer should only compile on Linux, as I haven't tested it (or linking it) on any other system.
|
|
||||||
Also, dlls/CMakeLists.txt must have a system-appropriate path to i386 version of GStreamer headers.
|
|
||||||
See set for ```ENV{PKG_CONFIG_PATH}```.
|
|
@ -41,6 +41,10 @@ if (USE_GSTREAMER AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
|
|||||||
add_definitions(-DUSE_GSTREAMER)
|
add_definitions(-DUSE_GSTREAMER)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (USE_MINIAUDIO)
|
||||||
|
add_definitions(-DUSE_MINIAUDIO)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (USE_FMOD AND (WIN32 OR NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")))
|
if (USE_FMOD AND (WIN32 OR NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")))
|
||||||
add_definitions(-DUSE_FMOD)
|
add_definitions(-DUSE_FMOD)
|
||||||
endif()
|
endif()
|
||||||
|
@ -18,6 +18,8 @@ This code is a placeholder for systems that support neither gstreamer nor fmod.
|
|||||||
|
|
||||||
#ifdef USE_GSTREAMER
|
#ifdef USE_GSTREAMER
|
||||||
#include "musicgstreamer.cpp"
|
#include "musicgstreamer.cpp"
|
||||||
|
#elif defined(USE_MINIAUDIO)
|
||||||
|
#include "musicminiaudio.cpp"
|
||||||
#elif defined(USE_FMOD)
|
#elif defined(USE_FMOD)
|
||||||
#include "musicfmod.cpp"
|
#include "musicfmod.cpp"
|
||||||
#else
|
#else
|
||||||
|
495
dlls/musicminiaudio.cpp
Normal file
495
dlls/musicminiaudio.cpp
Normal file
@ -0,0 +1,495 @@
|
|||||||
|
//-------------------------------------------------------------
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-
|
||||||
|
//- musicminiaudio.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 "extdll.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "cbase.h"
|
||||||
|
|
||||||
|
#include "musicminiaudio.h"
|
||||||
|
|
||||||
|
//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
|
||||||
|
|
||||||
|
CMusic g_MusicPlayer;
|
||||||
|
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) {
|
||||||
|
ALERT ( at_console, "MUSICPLAYER : unable to initialize\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bInit = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// 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 ( 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, "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 )
|
||||||
|
{
|
||||||
|
ALERT ( at_console, "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 )
|
||||||
|
{
|
||||||
|
ALERT ( at_console, "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 )
|
||||||
|
{
|
||||||
|
ALERT ( at_console, "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);
|
||||||
|
|
||||||
|
ALERT ( at_console, "MUSICPLAYER : Opening file %s.\n", payload );
|
||||||
|
|
||||||
|
result = ma_decoder_init_file(payload, NULL, &decoder);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
ALERT ( at_console, "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;
|
||||||
|
|
||||||
|
ALERT ( at_console, "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.
|
||||||
|
ALERT ( at_console, "MUSICPLAYER : Failed to change playback device configuration.\n" );
|
||||||
|
g_MusicPlayer.m_bInit = FALSE; //We have been deinitialized. This is NOT ideal.
|
||||||
|
return;
|
||||||
|
}else
|
||||||
|
ALERT ( at_console, "MUSICPLAYER : New configuration applied successfully.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// playback
|
||||||
|
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||||
|
ALERT ( at_console, "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 )
|
||||||
|
ALERT ( at_console, "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
|
||||||
|
{
|
||||||
|
ALERT ( at_console, "MUSICPLAYER : Terminating and unloading.\n" );
|
||||||
|
ma_device_uninit(&device);
|
||||||
|
ma_decoder_uninit(&decoder);
|
||||||
|
g_MusicPlayer.m_bInit = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// 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 );
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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)"
|
||||||
|
]
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*//---------------
|
||||||
|
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 ...
|
||||||
|
|
||||||
|
*///---------------
|
83
dlls/musicminiaudio.h
Normal file
83
dlls/musicminiaudio.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//-------------------------------------------------------------
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
//-
|
||||||
|
//- musicminiaudio.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 MUSIC_H
|
||||||
|
#define MUSIC_H
|
||||||
|
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include "../miniaudio/miniaudio.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 ); // 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;
|
||||||
|
|
||||||
|
void songEnd();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CMusic g_MusicPlayer;
|
||||||
|
#endif // MUSIC_H
|
1
miniaudio
Submodule
1
miniaudio
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 4d813cfe23c28db165cce6785419fee9d2399766
|
Loading…
x
Reference in New Issue
Block a user