Skip to content

Commit 6762f18

Browse files
committed
bass: expose IGModAudioChannelEncoder to Lua
1 parent 01eaf33 commit 6762f18

File tree

4 files changed

+104
-52
lines changed

4 files changed

+104
-52
lines changed

source/modules/bass.cpp

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,6 @@ LUA_FUNCTION_STATIC(IGModAudioChannel_Restart)
334334
return 0;
335335
}
336336

337-
338-
339337
class BassEncoderCallback : public IGModEncoderCallback
340338
{
341339
public:
@@ -355,12 +353,8 @@ class BassEncoderCallback : public IGModEncoderCallback
355353
}
356354
};
357355

358-
virtual bool ShouldForceFinish(IGModAudioChannelEncoder* pEncoder, void* nSignalData)
359-
{
360-
if (m_pLua == nSignalData)
361-
return true; // Force finish as this is our signal that our interface is shutting down!
362-
363-
return false;
356+
virtual bool ShouldForceFinish(IGModAudioChannelEncoder* pEncoder, void* nSignalData) {
357+
return m_pLua == nSignalData; // Force finish as this is our signal that our interface is shutting down!
364358
};
365359

366360
virtual void OnFinish(IGModAudioChannelEncoder* pEncoder, GModEncoderStatus nStatus)
@@ -388,7 +382,7 @@ class BassEncoderCallback : public IGModEncoderCallback
388382
int m_nCallbackReference = -1;
389383
};
390384

391-
LUA_FUNCTION_STATIC(IGModAudioChannel_EncodeToDisk)
385+
LUA_FUNCTION_STATIC(IGModAudioChannel_WriteToDisk)
392386
{
393387
IGModAudioChannel* channel = Get_IGModAudioChannel(LUA, 1, true);
394388

@@ -464,17 +458,42 @@ LUA_FUNCTION_STATIC(IGModAudioChannel_DestroyLink)
464458
return 2;
465459
}
466460

467-
LUA_FUNCTION_STATIC(IGModAudioChannel_MakeServer)
461+
PushReferenced_LuaClass(IGModAudioChannelEncoder)
462+
Get_LuaClass(IGModAudioChannelEncoder, "IGModAudioChannelEncoder")
463+
464+
Default__index(IGModAudioChannelEncoder);
465+
Default__newindex(IGModAudioChannelEncoder);
466+
Default__GetTable(IGModAudioChannelEncoder);
467+
Default__gc(IGModAudioChannelEncoder,
468+
IGModAudioChannelEncoder* channel = (IGModAudioChannelEncoder*)pStoredData;
469+
if (channel)
470+
delete channel;
471+
)
472+
473+
LUA_FUNCTION_STATIC(IGModAudioChannelEncoder__tostring)
468474
{
469-
IGModAudioChannel* channel = Get_IGModAudioChannel(LUA, 1, true);
475+
IGModAudioChannelEncoder* channel = Get_IGModAudioChannelEncoder(LUA, 1, false);
476+
if (!channel)
477+
{
478+
LUA->PushString("IGModAudioChannelEncoder [NULL]");
479+
return 1;
480+
}
481+
482+
LUA->PushString("IGModAudioChannelEncoder");
483+
return 1;
484+
}
485+
486+
LUA_FUNCTION_STATIC(IGModAudioChannelEncoder_MakeServer)
487+
{
488+
IGModAudioChannelEncoder* encoder = Get_IGModAudioChannelEncoder(LUA, 1, true);
470489

471490
const char* strPort = LUA->CheckString(2);
472491
unsigned long nBuffer = (unsigned long)LUA->CheckNumber(3);
473492
unsigned long nBurst = (unsigned long)LUA->CheckNumber(4);
474493
unsigned long nFlags = (unsigned long)LUA->CheckNumber(5);
475494

476495
const char* pErrorCode = nullptr;
477-
LUA->PushBool(channel->MakeServer(strPort, nBuffer, nBurst, nFlags, &pErrorCode));
496+
LUA->PushBool(encoder->MakeServer(strPort, nBuffer, nBurst, nFlags, &pErrorCode));
478497
if (pErrorCode) {
479498
LUA->PushString(pErrorCode);
480499
} else {
@@ -483,17 +502,51 @@ LUA_FUNCTION_STATIC(IGModAudioChannel_MakeServer)
483502
return 2;
484503
}
485504

486-
Push_LuaClass(IGModAudioChannelEncoder)
487-
Get_LuaClass(IGModAudioChannelEncoder, "IGModAudioChannelEncoder")
505+
class BassEncoderDeletionCallback : public IGModEncoderCallback
506+
{
507+
public:
508+
BassEncoderDeletionCallback(GarrysMod::Lua::ILuaInterface* pLua) {
509+
m_pLua = pLua;
510+
}
488511

489-
Default__index(IGModAudioChannelEncoder);
490-
Default__newindex(IGModAudioChannelEncoder);
491-
Default__GetTable(IGModAudioChannelEncoder);
492-
Default__gc(IGModAudioChannelEncoder,
493-
IGModAudioChannelEncoder* channel = (IGModAudioChannelEncoder*)pStoredData;
494-
if (channel)
495-
delete channel;
496-
)
512+
virtual bool ShouldForceFinish(IGModAudioChannelEncoder* pEncoder, void* nSignalData) {
513+
return m_pLua == nSignalData;
514+
};
515+
516+
virtual void OnFinish(IGModAudioChannelEncoder* pEncoder, GModEncoderStatus nStatus)
517+
{
518+
// The IGModAudioChannelEncoder deletes itself, so we gotta ensure no invalid pointers are left in Lua
519+
Delete_IGModAudioChannelEncoder(m_pLua, pEncoder);
520+
}
521+
private:
522+
GarrysMod::Lua::ILuaInterface* m_pLua;
523+
};
524+
525+
LUA_FUNCTION_STATIC(IGModAudioChannel_CreateEncoder)
526+
{
527+
IGModAudioChannel* channel = Get_IGModAudioChannel(LUA, 1, true);
528+
529+
const char* pFileName = LUA->CheckString(2);
530+
// NOTE: Next time ensure I fucking use CheckNumber and not CheckString to then cast :sob: only took 8+ hours to figure out
531+
unsigned long nFlags = (unsigned long)LUA->CheckNumber(3);
532+
533+
LUA->Push(4);
534+
BassEncoderDeletionCallback* pCallback = new BassEncoderDeletionCallback(LUA);
535+
// We do not manage this pointer! GModAudio does for us
536+
537+
const char* pErrorMsg = NULL;
538+
IGModAudioChannelEncoder* pEncoder = channel->CreateEncoder(pFileName, nFlags, pCallback, &pErrorMsg);
539+
if (pErrorMsg)
540+
{
541+
LUA->PushBool(false);
542+
LUA->PushString(pErrorMsg);
543+
return 2;
544+
}
545+
546+
Push_IGModAudioChannelEncoder(LUA, pEncoder);
547+
LUA->PushNil();
548+
return 2;
549+
}
497550

498551
LUA_FUNCTION_STATIC(bass_PlayFile)
499552
{
@@ -613,6 +666,7 @@ void CBassModule::LuaInit(GarrysMod::Lua::ILuaInterface* pLua, bool bServerInit)
613666
Util::AddFunc(pLua, IGModAudioChannelEncoder__gc, "__gc");
614667
Util::AddFunc(pLua, IGModAudioChannelEncoder__index, "__index");
615668
Util::AddFunc(pLua, IGModAudioChannelEncoder__newindex, "__newindex");
669+
Util::AddFunc(pLua, IGModAudioChannelEncoder_MakeServer, "MakeServer");
616670
pLua->Pop(1);
617671

618672
Lua::GetLuaData(pLua)->RegisterMetaTable(Lua::IGModAudioChannel, pLua->CreateMetaTable("IGModAudioChannel"));
@@ -661,11 +715,11 @@ void CBassModule::LuaInit(GarrysMod::Lua::ILuaInterface* pLua, bool bServerInit)
661715
Util::AddFunc(pLua, IGModAudioChannel_NotImplemented, "Set3DEnabled");
662716

663717
// HolyLib specific
664-
Util::AddFunc(pLua, IGModAudioChannel_EncodeToDisk, "EncodeToDisk");
718+
Util::AddFunc(pLua, IGModAudioChannel_WriteToDisk, "WriteToDisk");
719+
Util::AddFunc(pLua, IGModAudioChannel_CreateEncoder, "CreateEncoder");
665720
Util::AddFunc(pLua, IGModAudioChannel_Update, "Update");
666721
Util::AddFunc(pLua, IGModAudioChannel_CreateLink, "CreateLink");
667722
Util::AddFunc(pLua, IGModAudioChannel_DestroyLink, "DestroyLink");
668-
Util::AddFunc(pLua, IGModAudioChannel_MakeServer, "MakeServer");
669723
pLua->Pop(1);
670724

671725
Util::StartTable(pLua);

source/sourcesdk/IGmod_Audio.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class IGModAudioChannelEncoder
3838
virtual bool GetLastError(const char** pErrorOut) = 0;
3939
// Wasn't exposed since CreateEncoder already calls it so it has no real use
4040
// virtual void InitEncoder(unsigned long nEncoderFlags) = 0;
41+
42+
virtual bool MakeServer( const char* port, unsigned long buffer, unsigned long burst, unsigned long flags, const char** pErrorOut ) = 0;
4143
};
4244

4345
class IGModAudioChannelEncoder;
@@ -97,7 +99,6 @@ class IGModAudioChannel
9799
virtual void Update( unsigned long length ) = 0; // Updates the playback buffer
98100
virtual bool CreateLink( IGModAudioChannel* pChannel, const char** pErrorOut ) = 0;
99101
virtual bool DestroyLink( IGModAudioChannel* pChannel, const char** pErrorOut ) = 0;
100-
virtual bool MakeServer( const char* port, unsigned long buffer, unsigned long burst, unsigned long flags, const char** pErrorOut ) = 0;
101102
};
102103

103104
class IAudioStreamEvent;

source/sourcesdk/cgmod_audio.cpp

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,25 +1024,6 @@ bool CGModAudioChannel::DestroyLink( IGModAudioChannel* pChannel, const char** p
10241024
return false;
10251025
}
10261026

1027-
bool CGModAudioChannel::MakeServer( const char* port, unsigned long buffer, unsigned long burst, unsigned long flags, const char** pErrorOut )
1028-
{
1029-
*pErrorOut = NULL;
1030-
HENCODE encoder = func_BASS_Encode_Start(m_pHandle, NULL, BASS_ENCODE_PCM | BASS_ENCODE_NOHEAD, NULL, NULL);
1031-
if (!encoder)
1032-
{
1033-
*pErrorOut = BassErrorToString(BASS_ErrorGetCode());
1034-
return false;
1035-
}
1036-
1037-
if (func_BASS_Encode_ServerInit(encoder, port, buffer, burst, flags, NULL, NULL) == 0)
1038-
{
1039-
*pErrorOut = BassErrorToString(BASS_ErrorGetCode());
1040-
return false;
1041-
}
1042-
1043-
return true;
1044-
}
1045-
10461027
// What went wrong...
10471028
// I don't know why but BASS just shits itself, like when ProcessChannel gets called it does not work at all.
10481029
CGModAudioChannelEncoder::CGModAudioChannelEncoder(DWORD pChannel, const char* pFileName, IGModEncoderCallback* pCallback)
@@ -1054,7 +1035,7 @@ CGModAudioChannelEncoder::CGModAudioChannelEncoder(DWORD pChannel, const char* p
10541035
m_nStatus = GModEncoderStatus::NONE;
10551036
m_strLastError = "";
10561037
m_pEncoder = NULL;
1057-
m_pFileHandle = NULL;
1038+
m_pFileHandle = NULL; // Can be NULL when given "" as a filename
10581039

10591040
g_CGMod_Audio.AddEncoder(this);
10601041

@@ -1080,9 +1061,7 @@ CGModAudioChannelEncoder::~CGModAudioChannelEncoder()
10801061
g_CGMod_Audio.RemoveEncoder(this);
10811062

10821063
if (m_pEncoder)
1083-
{
10841064
Stop(false); // Free encoder
1085-
}
10861065

10871066
// Invalidate pointers and such, fileHandle could still be valid
10881067
OnEncoderFreed();
@@ -1151,10 +1130,13 @@ if (!func) { \
11511130

11521131
void CGModAudioChannelEncoder::InitEncoder(unsigned long nEncoderFlags)
11531132
{
1154-
m_pFileHandle = g_pFullFileSystem->Open(m_strFileName.c_str(), "wb", "DATA");
1155-
if (!m_pFileHandle) {
1156-
m_strLastError = BassErrorToString(BASS_ERROR_FILEOPEN);
1157-
return;
1133+
if (m_strFileName.length() > 0)
1134+
{
1135+
m_pFileHandle = g_pFullFileSystem->Open(m_strFileName.c_str(), "wb", "DATA");
1136+
if (!m_pFileHandle) {
1137+
m_strLastError = BassErrorToString(BASS_ERROR_FILEOPEN);
1138+
return;
1139+
}
11581140
}
11591141

11601142
std::string fname(m_strFileName);
@@ -1207,6 +1189,9 @@ void CGModAudioChannelEncoder::HandleFinish(void* nSignalData)
12071189

12081190
void CGModAudioChannelEncoder::WriteToFile(const void* pBuffer, unsigned long nLength)
12091191
{
1192+
if (!m_pFileHandle)
1193+
return;
1194+
12101195
g_pFullFileSystem->Write(pBuffer, nLength, (FileHandle_t)m_pFileHandle);
12111196
}
12121197

@@ -1249,4 +1234,16 @@ void CALLBACK CGModAudioChannelEncoder::EncoderFreedCallback(HENCODE handle, DWO
12491234
} else if (status == BASS_ENCODE_NOTIFY_ENCODER) {
12501235
((CGModAudioChannelEncoder*)user)->OnEncoderDied();
12511236
}
1237+
}
1238+
1239+
bool CGModAudioChannelEncoder::MakeServer( const char* port, unsigned long buffer, unsigned long burst, unsigned long flags, const char** pErrorOut )
1240+
{
1241+
*pErrorOut = NULL;
1242+
if (func_BASS_Encode_ServerInit(m_pEncoder, port, buffer, burst, flags, NULL, NULL) == 0)
1243+
{
1244+
*pErrorOut = BassErrorToString(BASS_ErrorGetCode());
1245+
return false;
1246+
}
1247+
1248+
return true;
12521249
}

source/sourcesdk/cgmod_audio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CGModAudioChannelEncoder : public IGModAudioChannelEncoder
4747
// Returns true if there was an error, pErrorOut will either be filled or NULL
4848
// If it returns true, it will also invalidate/free itself so the pointer becomes invalid!
4949
virtual bool GetLastError(const char** pErrorOut);
50+
virtual bool MakeServer( const char* port, unsigned long buffer, unsigned long burst, unsigned long flags, const char** pErrorOut );
5051

5152
public: // Non virtual
5253
CGModAudioChannelEncoder(DWORD pChannel, const char* pFileName, IGModEncoderCallback* pCallback );
@@ -119,7 +120,6 @@ class CGModAudioChannel : public IGModAudioChannel
119120
virtual void Update( unsigned long length );
120121
virtual bool CreateLink( IGModAudioChannel* pChannel, const char** pErrorOut );
121122
virtual bool DestroyLink( IGModAudioChannel* pChannel, const char** pErrorOut );
122-
virtual bool MakeServer( const char* port, unsigned long buffer, unsigned long burst, unsigned long flags, const char** pErrorOut );
123123
public:
124124
CGModAudioChannel( DWORD handle, bool isfile, const char* pFileName = NULL );
125125
virtual ~CGModAudioChannel();

0 commit comments

Comments
 (0)