Browse Source

Merge pull request #273 from RoyShapiro/invasion

HL:Invasion Add MiniAudio Music implementation
invasion
nekonomicon 2 years ago committed by GitHub
parent
commit
710fb2bb5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .gitmodules
  2. 3
      CMakeLists.txt
  3. 21
      README.md
  4. 5
      cl_dll/CMakeLists.txt
  5. 443
      cl_dll/clientmusic.cpp
  6. 97
      cl_dll/clientmusic.h
  7. 1
      cl_dll/hud.cpp
  8. 9
      cl_dll/hud.h
  9. 11
      cl_dll/hud_spectator.h
  10. 308
      cl_dll/view.cpp
  11. 46
      dlls/CMakeLists.txt
  12. 1091
      dlls/fmod.h
  13. 32
      dlls/fmod_errors.h
  14. 89
      dlls/music.cpp
  15. 73
      dlls/music.h
  16. 446
      dlls/musicfmod.cpp
  17. 94
      dlls/musicfmod.h
  18. 511
      dlls/musicgstreamer.cpp
  19. 85
      dlls/musicgstreamer.h
  20. 2
      dlls/player.cpp
  21. 1
      miniaudio

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

3
CMakeLists.txt

@ -48,8 +48,7 @@ option(USE_VOICEMGR "Enable VOICE MANAGER." OFF)
option(BUILD_CLIENT "Build client dll" ON) 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(DISABLE_MINIAUDIO "Disable Miniaudio." OFF)
option(USE_FMOD "Enable FMOD." OFF)
if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR
((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") ((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")

21
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,18 @@ 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
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,
also it builds with miniaudio by default, thus update the modules when clonning.
sudo apt install libgstreamer1.0:i386 #to play with music (also install plugins) A miniaudio music player implementation is used to allow music during gameplay,
sudo apt install libgstreamer1.0-dev:i386 #to compile with music (-DUSE_GSTREAMER=1) if it can not be used in your environment, it can be disabled with the use of:
-DDISABLE_MINIAUDIO=1 cmake option.
Also added -DUSE_FMOD option for cmake and tried my best to prevent it being used in Linux (uses windows.h include).
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}```.

5
cl_dll/CMakeLists.txt

@ -46,6 +46,10 @@ if (GOLDSOURCE_SUPPORT)
add_definitions(-DGOLDSOURCE_SUPPORT) add_definitions(-DGOLDSOURCE_SUPPORT)
endif() endif()
if (DISABLE_MINIAUDIO)
add_definitions(-DDISABLE_MINIAUDIO)
endif()
if (USE_VGUI) if (USE_VGUI)
add_definitions(-DUSE_VGUI) add_definitions(-DUSE_VGUI)
if (USE_NOVGUI_MOTD) if (USE_NOVGUI_MOTD)
@ -73,6 +77,7 @@ set (CLDLL_SOURCES
hudzoom.cpp hudzoom.cpp
lensflare.cpp lensflare.cpp
nvg.cpp nvg.cpp
clientmusic.cpp
particules.cpp particules.cpp
studio_util.cpp studio_util.cpp
StudioModelRenderer.cpp StudioModelRenderer.cpp

443
cl_dll/clientmusic.cpp

@ -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 ...
*///---------------

97
cl_dll/clientmusic.h

@ -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
cl_dll/hud.cpp

@ -469,6 +469,7 @@ void CHud::Init( void )
m_Particules.Init(); m_Particules.Init();
m_Sniper.Init(); m_Sniper.Init();
m_NVG.Init(); m_NVG.Init();
m_MusicPlayer.Init(); //modif de Roy, we need to initialize the music player's message receiver (see hud.h)
m_RPG.Init(); m_RPG.Init();
m_Fog.Init(); m_Fog.Init();
m_LFlammes.Init(); m_LFlammes.Init();

9
cl_dll/hud.h

@ -801,7 +801,13 @@ public:
}; };
// modif de Roy
class CHudMusic : public CHudBase // This class is simply a message receiver for the music player
{
public: //The methods are implemented in clientmusic.cpp
int Init( void ); //This gets called from hud.cpp
int MsgFunc_CMusicOpen ( const char *pszName, int iSize, void *pbuf );
};
// modif de Julien // modif de Julien
// //
@ -1078,6 +1084,7 @@ public:
CHudParticules m_Particules; CHudParticules m_Particules;
CHudSniper m_Sniper; CHudSniper m_Sniper;
CHudNVG m_NVG; CHudNVG m_NVG;
CHudMusic m_MusicPlayer; //modif de Roy, we need an instance of the music player's message receiver
CHudRPG m_RPG; CHudRPG m_RPG;
CHudFog m_Fog; CHudFog m_Fog;
CHudLFlammes m_LFlammes; CHudLFlammes m_LFlammes;

11
cl_dll/hud_spectator.h

@ -17,12 +17,6 @@
#define INSET_MAP_FREE 3 #define INSET_MAP_FREE 3
#define INSET_MAP_CHASE 4 #define INSET_MAP_CHASE 4
#define MAIN_CHASE_LOCKED 1 //modif de Julien o para Julien, old map definitions.
#define MAIN_CHASE_FREE 2
#define MAIN_ROAMING 3
#define MAIN_IN_EYE 4
#define MAIN_MAP_FREE 5
#define MAX_SPEC_HUD_MESSAGES 8 #define MAX_SPEC_HUD_MESSAGES 8
#define OVERVIEW_TILE_SIZE 128 // don't change this #define OVERVIEW_TILE_SIZE 128 // don't change this
@ -87,11 +81,6 @@ public:
int Draw( float flTime ); int Draw( float flTime );
int m_iMainMode; //modif de Julien o para Julien
int m_iInsetMode; //old stuff HLINVASION TODO Check what this stuff actually does
int m_iObserverTarget; //and more old stuff. (Not observerFlags!)
vec3_t m_mapAngles; // cuurent map view angles (cameraAngles?)
int m_iDrawCycle; int m_iDrawCycle;
client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES]; client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES];
char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128]; char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128];

308
cl_dll/view.cpp

@ -35,7 +35,6 @@
// modif de Julien // modif de Julien
extern float in_fov; extern float in_fov;
// Spectator Mode // Spectator Mode
extern "C" extern "C"
{ {
@ -123,7 +122,6 @@ cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", 0, 0.3};
float v_idlescale; // used by TFC for concussion grenade effect float v_idlescale; // used by TFC for concussion grenade effect
/*
//============================================================================= //=============================================================================
/* /*
void V_NormalizeAngles( float *angles ) void V_NormalizeAngles( float *angles )
@ -569,21 +567,9 @@ void V_CalcNormalRefdef( struct ref_params_s *pparams )
AngleVectors( camAngles, camForward, camRight, camUp ); AngleVectors( camAngles, camForward, camRight, camUp );
for( i = 0; i < 3; i++ )
/* // modif de Julien
if ( gHUD.m_HudTank.m_iPlayerInTank == true )
{
VectorCopy( gEngfuncs.GetEntityByIndex( gHUD.m_HudTank.m_iCamEnt - 1 )->origin, pparams->vieworg );
for ( i = 0; i < 3; i++ )
pparams->vieworg[ i ] += -ofs[2] * camForward[ i ];
}
else*/
{ {
for ( i = 0; i < 3; i++ ) pparams->vieworg[i] += -ofs[2] * camForward[i];
{
pparams->vieworg[ i ] += -ofs[2] * camForward[ i ];
}
} }
} }
@ -753,7 +739,7 @@ void V_CalcNormalRefdef( struct ref_params_s *pparams )
VectorCopy( camAngles, pparams->viewangles ); VectorCopy( camAngles, pparams->viewangles );
} }
// Apply this at all times //HLINVASION Julien --> This whole section was only in the ThirdPerson if block above in Julien's code. // Apply this at all times
{ {
float pitch = camAngles[0]; float pitch = camAngles[0];
@ -803,286 +789,6 @@ void V_CalcNormalRefdef( struct ref_params_s *pparams )
if ( in_fov != 0 && in_fov != 90 ) if ( in_fov != 0 && in_fov != 90 )
view->model = NULL; view->model = NULL;
}
void V_GetInEyePos(int entity, float *origin, float * angles )
{
cl_entity_t * ent = gEngfuncs.GetEntityByIndex( entity );
if ( !ent )
return;
if ( !ent->player || g_PlayerInfoList[entity].name == NULL )
return;
VectorCopy ( ent->origin, origin );
VectorCopy ( ent->angles, angles );
angles[0]*=-M_PI;
if ( ent->curstate.solid == SOLID_NOT )
{
angles[ROLL] = 80; // dead view angle
origin[2]+= -8 ; // PM_DEAD_VIEWHEIGHT
}
else if (ent->curstate.usehull == 1 )
origin[2]+= 12; // VEC_DUCK_VIEW;
else
// exacty eye position can't be caluculated since it depends on
// client values like cl_bobcycle, this offset matches the default values
origin[2]+= 28; // DEFAULT_VIEWHEIGHT
}
/*
==================
V_CalcSpectatorRefdef
==================
*/
void V_CalcSpectatorRefdef ( struct ref_params_s *pparams )
{
cl_entity_t *ent, *view;
vec3_t angles;
static viewinterp_t ViewInterp;
static float lasttime;
static float lastang[3];
static float lastorg[3];
vec3_t delta;
// ent is the player model ( visible when out of body )
ent = gEngfuncs.GetLocalPlayer();
// view is the weapon model (only visible from inside body )
view = gEngfuncs.GetViewModel();
// refresh position
VectorCopy ( pparams->simorg, pparams->vieworg );
// done all the spectator smoothing only once in the first frame
// Observer angle capturing and smoothing
if ( iHasNewViewOrigin )
{
// Get the angles from the physics code
VectorCopy( vecNewViewOrigin, pparams->vieworg );
}
else
{
// otherwise copy normal vieworigin into vecNewViewOrigin
VectorCopy( pparams->vieworg, vecNewViewOrigin );
}
VectorCopy ( pparams->cl_viewangles, pparams->viewangles );
// Observer angle capturing and smoothing
if ( iHasNewViewAngles )
{
// Get the angles from the physics code
VectorCopy( vecNewViewAngles, pparams->viewangles );
}
else
{
// otherwise copy normal viewangle into vewNewViewAngles
VectorCopy( pparams->viewangles, vecNewViewAngles);
}
// do the smoothing only once per frame
if (pparams->nextView == 0)
{
// smooth angles
VectorSubtract( pparams->viewangles, lastang, delta );
if ( Length( delta ) != 0.0f )
{
VectorCopy( pparams->viewangles, ViewInterp.Angles[ ViewInterp.CurrentAngle & ORIGIN_MASK ] );
ViewInterp.AngleTime[ ViewInterp.CurrentAngle & ORIGIN_MASK ] = pparams->time;
ViewInterp.CurrentAngle++;
VectorCopy( pparams->viewangles, lastang );
}
if ( cl_vsmoothing && cl_vsmoothing->value && ( iIsSpectator & SPEC_SMOOTH_ANGLES ) )
{
int foundidx;
int i;
float t;
t = pparams->time - cl_vsmoothing->value;
for ( i = 1; i < ORIGIN_MASK; i++ )
{
foundidx = ViewInterp.CurrentAngle - 1 - i;
if ( ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ] <= t )
break;
}
if ( i < ORIGIN_MASK && ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ] != 0.0 )
{
// Interpolate
double dt;
float da;
vec3_t v1,v2;
AngleVectors( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], v1, NULL, NULL );
AngleVectors( ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], v2, NULL, NULL );
da = AngleBetweenVectors( v1, v2 );
dt = ViewInterp.AngleTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ];
if ( dt > 0.0 && ( da < 22.5f) )
{
double frac;
frac = ( t - ViewInterp.AngleTime[ foundidx & ORIGIN_MASK] ) / dt;
frac = Q_min( 1.0, frac );
// interpolate angles
InterpolateAngles( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], vecNewViewAngles, frac );
VectorCopy( vecNewViewAngles, pparams->viewangles );
}
}
}
// smooth origin
VectorSubtract( pparams->vieworg, lastorg, delta );
if ( Length( delta ) != 0.0 )
{
VectorCopy( pparams->vieworg, ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] );
ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time;
ViewInterp.CurrentOrigin++;
VectorCopy( pparams->vieworg, lastorg );
}
if ( cl_vsmoothing && cl_vsmoothing->value && ( iIsSpectator & SPEC_SMOOTH_ORIGIN ) )
{
int foundidx;
int i;
float t;
t = pparams->time - cl_vsmoothing->value;
for ( i = 1; i < ORIGIN_MASK; i++ )
{
foundidx = ViewInterp.CurrentOrigin - 1 - i;
if ( ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] <= t )
break;
}
if ( i < ORIGIN_MASK && ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] != 0.0 )
{
// Interpolate
vec3_t delta;
double frac;
double dt;
vec3_t neworg;
dt = ViewInterp.OriginTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ];
if ( dt > 0.0 )
{
frac = ( t - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK] ) / dt;
frac = Q_min( 1.0, frac );
VectorSubtract( ViewInterp.Origins[ ( foundidx + 1 ) & ORIGIN_MASK ], ViewInterp.Origins[ foundidx & ORIGIN_MASK ], delta );
VectorMA( ViewInterp.Origins[ foundidx & ORIGIN_MASK ], frac, delta, neworg );
// Dont interpolate large changes
if ( Length( delta ) < 64 )
{
VectorSubtract( neworg, pparams->simorg, delta );
VectorAdd( pparams->vieworg, delta, pparams->vieworg );
VectorCopy( pparams->vieworg, vecNewViewOrigin );
}
}
}
}
}
lasttime = pparams->time;
view->model = NULL;
if ( pparams->nextView == 0 )
{
// first renderer cycle
switch (gHUD.m_Spectator.m_iMainMode)
{
case MAIN_MAP_FREE : pparams->onlyClientDraw = true;
angles = pparams->cl_viewangles;
angles[0] = 51.25f + 38.75f*(angles[0]/90.0f);
VectorCopy ( angles, gHUD.m_Spectator.m_mapAngles );
gHUD.m_Spectator.GetMapPosition( pparams->vieworg );
VectorCopy ( angles, pparams->viewangles );
break;
case MAIN_IN_EYE : V_GetInEyePos( gHUD.m_Spectator.m_iObserverTarget,
pparams->vieworg, pparams->viewangles );
break;
default : pparams->onlyClientDraw = false;
break;
}
if ( gHUD.m_Spectator.m_iInsetMode != INSET_OFF )
pparams->nextView = 1; // force a second renderer view
gHUD.m_Spectator.m_iDrawCycle = 0;
}
else
{
// second renderer cycle
// set inset parameters
pparams->viewport[0] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowX); // change viewport to inset window
pparams->viewport[1] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowY);
pparams->viewport[2] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowWidth);
pparams->viewport[3] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowHeight);
pparams->nextView = 0; // on further view
pparams->onlyClientDraw = false;
// override some settings in certain modes
switch (gHUD.m_Spectator.m_iInsetMode)
{
case INSET_MAP_FREE : pparams->onlyClientDraw = true;
angles = pparams->cl_viewangles;
angles[0] = 51.25f + 38.75f*(angles[0]/90.0f);
VectorCopy ( angles, gHUD.m_Spectator.m_mapAngles );
gHUD.m_Spectator.GetMapPosition( pparams->vieworg );
VectorCopy ( angles, pparams->viewangles );
break;
case INSET_IN_EYE : V_GetInEyePos( gHUD.m_Spectator.m_iObserverTarget,
pparams->vieworg, pparams->viewangles );
break;
}
gHUD.m_Spectator.m_iDrawCycle = 1;
}
v_angles = pparams->viewangles;
v_origin = pparams->vieworg;
} }
void V_SmoothInterpolateAngles( float * startAngle, float * endAngle, float * finalAngle, float degreesPerSec ) void V_SmoothInterpolateAngles( float * startAngle, float * endAngle, float * finalAngle, float degreesPerSec )
@ -1527,7 +1233,7 @@ void V_ResetChaseCam()
v_resetCamera = true; v_resetCamera = true;
} }
/*void V_GetInEyePos( int target, float *origin, float *angles ) //Redefinition of the above //modif de Julien o para Julien void V_GetInEyePos( int target, float *origin, float *angles )
{ {
if( !target ) if( !target )
{ {
@ -1558,7 +1264,7 @@ void V_ResetChaseCam()
// exacty eye position can't be caluculated since it depends on // exacty eye position can't be caluculated since it depends on
// client values like cl_bobcycle, this offset matches the default values // client values like cl_bobcycle, this offset matches the default values
origin[2] += 28.0f; // DEFAULT_VIEWHEIGHT origin[2] += 28.0f; // DEFAULT_VIEWHEIGHT
}*/ }
void V_GetMapFreePosition( float *cl_angles, float *origin, float *angles ) void V_GetMapFreePosition( float *cl_angles, float *origin, float *angles )
{ {
@ -1674,7 +1380,7 @@ V_CalcSpectatorRefdef
================== ==================
*/ */
/*void V_CalcSpectatorRefdef( struct ref_params_s * pparams ) //Redefinition of the above //modif de Julien o para Julien void V_CalcSpectatorRefdef( struct ref_params_s * pparams )
{ {
static vec3_t velocity( 0.0f, 0.0f, 0.0f ); static vec3_t velocity( 0.0f, 0.0f, 0.0f );
@ -1832,7 +1538,7 @@ V_CalcSpectatorRefdef
VectorCopy( v_cl_angles, pparams->cl_viewangles ); VectorCopy( v_cl_angles, pparams->cl_viewangles );
VectorCopy( v_angles, pparams->viewangles ) VectorCopy( v_angles, pparams->viewangles )
VectorCopy( v_origin, pparams->vieworg ); VectorCopy( v_origin, pparams->vieworg );
}*/ }
void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams ) void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams )
{ {

46
dlls/CMakeLists.txt

@ -37,14 +37,6 @@ else()
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
endif() endif()
if (USE_GSTREAMER AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
add_definitions(-DUSE_GSTREAMER)
endif()
if (USE_FMOD AND (WIN32 OR NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")))
add_definitions(-DUSE_FMOD)
endif()
set (SVDLL_SOURCES set (SVDLL_SOURCES
aflock.cpp aflock.cpp
agrunt.cpp agrunt.cpp
@ -166,40 +158,7 @@ set (SVDLL_SOURCES
zombie.cpp zombie.cpp
) )
if (USE_GSTREAMER AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) include_directories (. wpn_shared ../common ../engine ../pm_shared ../game_shared ../public)
#if we're using gstreamer music
if (NOT 64BIT)
set(ENV{PKG_CONFIG_PATH} "/usr/lib/i386-linux-gnu/pkgconfig")
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB REQUIRED glib-2.0)
set(GSTREAMER_MINIMUM_VERSION 1.0.5)
pkg_check_modules(GST1_TEST gstreamer-1.0)
if ( GST1_TEST_FOUND AND NOT ${GST1_TEST_VERSION} VERSION_LESS ${GSTREAMER_MINIMUM_VERSION} )
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
add_definitions(-DGST_API_VERSION_1=1)
endif()
link_directories(
${GSTREAMER_LIBRARY_DIRS}
${GLIB_LIBRARY_DIRS}
)
set(GST_LIBRARIES
${GSTREAMER_LIBRARIES}
${GSTREAMER-APP_LIBRARIES}
${GSTREAMER-AUDIO_LIBRARIES}
${GSTREAMER-PBUTILS_LIBRARIES}
${GSTREAMER-FFT_LIBRARIES}
pthread
${GLIB_LIBRARIES}
${GLIB_GIO_LIBRARIES}
${GLIB_GOBJECT_LIBRARIES}
)
endif()
include_directories (. wpn_shared ../common ../engine ../pm_shared ../game_shared ../public ${GLIB_INCLUDE_DIRS} ${GSTREAMER_INCLUDE_DIRS})
if(MSVC) if(MSVC)
set(SVDLL_SOURCES set(SVDLL_SOURCES
@ -216,9 +175,6 @@ else()
endif() endif()
add_library (${SVDLL_LIBRARY} SHARED ${SVDLL_SOURCES}) add_library (${SVDLL_LIBRARY} SHARED ${SVDLL_SOURCES})
if (USE_GSTREAMER AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) #More gstreamer linkage stuff
target_link_libraries(${SVDLL_LIBRARY} ${GST_LIBRARIES})
endif()
set_target_properties (${SVDLL_LIBRARY} PROPERTIES set_target_properties (${SVDLL_LIBRARY} PROPERTIES
POSITION_INDEPENDENT_CODE 1) POSITION_INDEPENDENT_CODE 1)

1091
dlls/fmod.h

File diff suppressed because it is too large Load Diff

32
dlls/fmod_errors.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

89
dlls/music.cpp

@ -1,26 +1,22 @@
//--------------------------------------------------------- //-------------------------------------------------------------
//--------------------------------------------------------- //-------------------------------------------------------------
//- --- //-
//- music.cpp --- //- music.cpp
//- --- //-
//--------------------------------------------------------- //-------------------------------------------------------------
//--------------------------------------------------------- //-------------------------------------------------------------
//- by Roy, based on the code by JujU ----------- //- by Roy at suggestion by nekonomicon, based on code by JujU
//--------------------------------------------------------- //-------------------------------------------------------------
//- fake and null mp3 player code for HL mod ----------- //- mp3 player code for HL mod; trigger_music implementation
//--------------------------------------------------------- //-------------------------------------------------------------
//-
/*//--------------- //- This is the server-side code.
//- It implements trigger_music, which simply informs the
This code is a placeholder for systems that support neither gstreamer nor fmod. //- client when and what music needs to be played.
//- No actual playback happens here.
*///--------------- //- We just send a message containing file type and filename.
//-
#ifdef USE_GSTREAMER //-------------------------------------------------------------
#include "musicgstreamer.cpp"
#elif defined(USE_FMOD)
#include "musicfmod.cpp"
#else
//--------------------------------------------------------- //---------------------------------------------------------
// inclusions // inclusions
@ -29,27 +25,11 @@ This code is a placeholder for systems that support neither gstreamer nor fmod.
#include "util.h" #include "util.h"
#include "cbase.h" #include "cbase.h"
#include "music.h" extern int gmsgCMusicMessage; //This is simply a "handle" for the message. It's defined in player.cpp, can be defined here, but we'll follow the conventions.
CMusic g_MusicPlayer;
//Fake functions to have something to work with on Linux
//--------------------------------------------------------- //---------------------------------------------------------
// entity class
void CMusic :: Init ( void ){}
void CMusic :: OpenFile ( const char *filename, int repeat ){}
void CMusic :: OpenList ( const char *filename ){}
signed char EndCallback ( void *stream, void *buff, int len, int param )
{
return TRUE;
}
void CMusic :: Play ( void ){}
void CMusic :: Stop ( void ){}
void CMusic :: Reset ( void ){}
//---------------------------------------------------------
// The actual game entity
@ -66,11 +46,12 @@ public:
virtual int Save ( CSave &save ); virtual int Save ( CSave &save );
virtual int Restore ( CRestore &restore ); virtual int Restore ( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
string_t m_iFileName; // chemin du fichier string_t m_iFileName; // file path
int m_iFileType; // fichier texte ( liste ) ou fichier audio int m_iFileType; // text file (list) or audio file
}; };
@ -112,6 +93,24 @@ void CTriggerMusic :: KeyValue( KeyValueData *pkvd )
void CTriggerMusic :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) void CTriggerMusic :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{ {
return; MESSAGE_BEGIN( MSG_ALL, gmsgCMusicMessage, NULL ); //Inform the client side, we have some music to play.
WRITE_BYTE( m_iFileType ); //Send file type.
WRITE_STRING( STRING(m_iFileName) ); //Send file name.
MESSAGE_END();
} }
#endif
/*
FGD file entity 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)"
]
*/

73
dlls/music.h

@ -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

446
dlls/musicfmod.cpp

@ -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 ...
*///---------------

94
dlls/musicfmod.h

@ -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

511
dlls/musicgstreamer.cpp

@ -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 ...
*///---------------

85
dlls/musicgstreamer.h

@ -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

2
dlls/player.cpp

@ -234,6 +234,7 @@ int gmsgTankView = 0;
int gmsgRadioMsg = 0; int gmsgRadioMsg = 0;
int gmsgKeypad = 0; int gmsgKeypad = 0;
int gmsgConveyor = 0; int gmsgConveyor = 0;
int gmsgCMusicMessage = 0; //modif de Roy, Used by the music player to send filenames to the client side.
void LinkUserMessages( void ) void LinkUserMessages( void )
@ -321,6 +322,7 @@ void LinkUserMessages( void )
gmsgKeypad = REG_USER_MSG( "Keypad", -1); gmsgKeypad = REG_USER_MSG( "Keypad", -1);
gmsgConveyor = REG_USER_MSG( "Conveyor", -1); gmsgConveyor = REG_USER_MSG( "Conveyor", -1);
//fin de modifs de Julien //fin de modifs de Julien
gmsgCMusicMessage = REG_USER_MSG( "CMusicOpen", -1 ); //modif de Roy, Used by the music player to send filenames to the client side.
gmsgTeamNames = REG_USER_MSG( "TeamNames", -1 ); gmsgTeamNames = REG_USER_MSG( "TeamNames", -1 );
gmsgBhopcap = REG_USER_MSG( "Bhopcap", 1 ); gmsgBhopcap = REG_USER_MSG( "Bhopcap", 1 );

1
miniaudio

@ -0,0 +1 @@
Subproject commit 4d813cfe23c28db165cce6785419fee9d2399766
Loading…
Cancel
Save