allow libADLMIDI to be loaded dynamically
This commit is contained in:
parent
00a57d5a28
commit
ccb91d7362
|
@ -4254,6 +4254,7 @@ class DXXArchive(DXXCommon):
|
|||
'common/3d/points.cpp',
|
||||
'common/3d/rod.cpp',
|
||||
'common/3d/setup.cpp',
|
||||
'common/music/adlmidi_dynamic.cpp',
|
||||
'common/arch/sdl/event.cpp',
|
||||
'common/arch/sdl/joy.cpp',
|
||||
'common/arch/sdl/key.cpp',
|
||||
|
@ -4701,7 +4702,7 @@ class DXXProgram(DXXCommon):
|
|||
('__STDC_FORMAT_MACROS',),
|
||||
],
|
||||
CPPPATH = [os.path.join(self.srcdir, 'main')],
|
||||
LIBS = ['ADLMIDI', 'm'],
|
||||
LIBS = ['m', 'dl'],
|
||||
)
|
||||
|
||||
def register_program(self):
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "args.h"
|
||||
#include "hmp.h"
|
||||
#include "adlmidi.h"
|
||||
#include "adlmidi_dynamic.h"
|
||||
#include "digi_mixer_music.h"
|
||||
#include "strutil.h"
|
||||
#include "u_mem.h"
|
||||
|
@ -88,16 +88,6 @@ public:
|
|||
typename music_pointer::pointer get() { return m_music.get(); }
|
||||
};
|
||||
|
||||
struct ADLMIDI_delete
|
||||
{
|
||||
void operator()(ADL_MIDIPlayer *x)
|
||||
{
|
||||
adl_close(x);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<ADL_MIDIPlayer, ADLMIDI_delete> ADL_MIDIPlayer_t;
|
||||
|
||||
}
|
||||
|
||||
static current_music_t current_music;
|
||||
|
@ -112,16 +102,20 @@ static ADL_MIDIPlayer *get_adlmidi()
|
|||
int sample_rate;
|
||||
Mix_QuerySpec(&sample_rate, nullptr, nullptr);
|
||||
adlmidi = adl_init(sample_rate);
|
||||
adl_switchEmulator(adlmidi, ADLMIDI_EMU_DOSBOX);
|
||||
adl_setNumChips(adlmidi, 6);
|
||||
adl_setBank(adlmidi, 31);
|
||||
adl_setSoftPanEnabled(adlmidi, 1);
|
||||
current_adlmidi.reset(adlmidi);
|
||||
if (adlmidi)
|
||||
{
|
||||
adl_switchEmulator(adlmidi, ADLMIDI_EMU_DOSBOX);
|
||||
adl_setNumChips(adlmidi, 6);
|
||||
adl_setBank(adlmidi, static_cast<int>(ADL_EmbeddedBank::LBA_4OP));
|
||||
adl_setSoftPanEnabled(adlmidi, 1);
|
||||
current_adlmidi.reset(adlmidi);
|
||||
}
|
||||
}
|
||||
return adlmidi;
|
||||
}
|
||||
|
||||
enum class CurrentMusicType {
|
||||
enum class CurrentMusicType
|
||||
{
|
||||
None,
|
||||
ADLMIDI,
|
||||
SDLMixer,
|
||||
|
@ -277,7 +271,7 @@ static CurrentMusicType load_mus_data(const uint8_t *data, size_t size)
|
|||
ADL_MIDIPlayer *adlmidi = get_adlmidi();
|
||||
SDL_RWops *rw = NULL;
|
||||
|
||||
if (adl_openData(adlmidi, data, size) == 0)
|
||||
if (adlmidi && adl_openData(adlmidi, data, size) == 0)
|
||||
type = CurrentMusicType::ADLMIDI;
|
||||
else
|
||||
{
|
||||
|
@ -295,7 +289,7 @@ static CurrentMusicType load_mus_file(const char *filename)
|
|||
CurrentMusicType type = CurrentMusicType::None;
|
||||
ADL_MIDIPlayer *adlmidi = get_adlmidi();
|
||||
|
||||
if (adl_openFile(adlmidi, filename) == 0)
|
||||
if (adlmidi && adl_openFile(adlmidi, filename) == 0)
|
||||
type = CurrentMusicType::ADLMIDI;
|
||||
else
|
||||
{
|
||||
|
|
74
common/include/adlmidi_dynamic.h
Normal file
74
common/include/adlmidi_dynamic.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
/*
|
||||
* This is a dynamic interface to libADLMIDI, the OPL3 synthesizer library.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
struct ADL_MIDIPlayer;
|
||||
|
||||
enum ADLMIDI_SampleType
|
||||
{
|
||||
ADLMIDI_SampleType_S16 = 0
|
||||
};
|
||||
|
||||
struct ADLMIDI_AudioFormat
|
||||
{
|
||||
enum ADLMIDI_SampleType type;
|
||||
unsigned containerSize;
|
||||
unsigned sampleOffset;
|
||||
};
|
||||
|
||||
enum ADL_Emulator
|
||||
{
|
||||
ADLMIDI_EMU_DOSBOX = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* A few embedded bank numbers.
|
||||
*/
|
||||
enum class ADL_EmbeddedBank
|
||||
{
|
||||
MILES_AIL = 0,
|
||||
BISQWIT = 1,
|
||||
DESCENT = 2,
|
||||
// DESCENT_INT = 3,
|
||||
// DESCENT_HAM = 4,
|
||||
// DESCENT_RICK = 5,
|
||||
// DESCENT2 = 6,
|
||||
LBA_4OP = 31,
|
||||
THE_FATMAN_2OP = 58,
|
||||
THE_FATMAN_4OP = 59,
|
||||
JAMIE_OCONNELL = 66,
|
||||
NGUYEN_WOHLSTAND_4OP = 68,
|
||||
DMXOPL3 = 72,
|
||||
APOGEE_IMF90 = 74,
|
||||
};
|
||||
|
||||
extern ADL_MIDIPlayer *(*adl_init)(long sample_rate);
|
||||
extern void (*adl_close)(ADL_MIDIPlayer *device);
|
||||
extern int (*adl_switchEmulator)(ADL_MIDIPlayer *device, int emulator);
|
||||
extern int (*adl_setNumChips)(ADL_MIDIPlayer *device, int numChips);
|
||||
extern int (*adl_setBank)(ADL_MIDIPlayer *device, int bank);
|
||||
extern int (*adl_openBankFile)(ADL_MIDIPlayer *device, const char *filePath);
|
||||
extern void (*adl_setSoftPanEnabled)(ADL_MIDIPlayer *device, int softPanEn);
|
||||
extern void (*adl_setLoopEnabled)(ADL_MIDIPlayer *device, int loopEn);
|
||||
extern int (*adl_openData)(ADL_MIDIPlayer *device, const void *mem, unsigned long size);
|
||||
extern int (*adl_openFile)(ADL_MIDIPlayer *device, const char *filePath);
|
||||
extern int (*adl_playFormat)(ADL_MIDIPlayer *device, int sampleCount, uint8_t *left, uint8_t *right, const ADLMIDI_AudioFormat *format);
|
||||
|
||||
struct ADLMIDI_delete
|
||||
{
|
||||
void operator()(ADL_MIDIPlayer *x)
|
||||
{
|
||||
adl_close(x);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<ADL_MIDIPlayer, ADLMIDI_delete> ADL_MIDIPlayer_t;
|
100
common/music/adlmidi_dynamic.cpp
Normal file
100
common/music/adlmidi_dynamic.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
/*
|
||||
* This is a dynamic interface to libADLMIDI, the OPL3 synthesizer library.
|
||||
*/
|
||||
|
||||
#include "adlmidi_dynamic.h"
|
||||
#include "console.h"
|
||||
#if !defined(_WIN32)
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
enum
|
||||
{
|
||||
RTLD_LAZY = 1, RTLD_NOW = 2
|
||||
};
|
||||
|
||||
void *dlopen(const char *filename, int)
|
||||
{
|
||||
return LoadLibraryA(filename);
|
||||
}
|
||||
|
||||
void dlclose(void *handle)
|
||||
{
|
||||
FreeLibrary(reinterpret_cast<HMODULE>(handle));
|
||||
}
|
||||
|
||||
void *dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
return reinterpret_cast<void *>(
|
||||
GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol));
|
||||
}
|
||||
#endif
|
||||
|
||||
static ADL_MIDIPlayer *adl_init_failure(long)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class F>
|
||||
static bool load_function(void *handle, const char *name, F *&fptr)
|
||||
{
|
||||
fptr = reinterpret_cast<F *>(dlsym(handle, name));
|
||||
if (!fptr)
|
||||
con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic function \"%s\"", name);
|
||||
return fptr != nullptr;
|
||||
}
|
||||
|
||||
static ADL_MIDIPlayer *adl_init_first_call(long sample_rate)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
const char *library_name = "libADLMIDI.dll";
|
||||
#elif defined(__APPLE__)
|
||||
const char *library_name = "libADLMIDI.dylib";
|
||||
#else
|
||||
const char *library_name = "libADLMIDI.so";
|
||||
#endif
|
||||
void *handle = dlopen(library_name, RTLD_LAZY);
|
||||
if (!handle ||
|
||||
!load_function(handle, "adl_init", adl_init) ||
|
||||
!load_function(handle, "adl_close", adl_close) ||
|
||||
!load_function(handle, "adl_switchEmulator", adl_switchEmulator) ||
|
||||
!load_function(handle, "adl_setNumChips", adl_setNumChips) ||
|
||||
!load_function(handle, "adl_setBank", adl_setBank) ||
|
||||
!load_function(handle, "adl_openBankFile", adl_openBankFile) ||
|
||||
!load_function(handle, "adl_setSoftPanEnabled", adl_setSoftPanEnabled) ||
|
||||
!load_function(handle, "adl_setLoopEnabled", adl_setLoopEnabled) ||
|
||||
!load_function(handle, "adl_openData", adl_openData) ||
|
||||
!load_function(handle, "adl_openFile", adl_openFile) ||
|
||||
!load_function(handle, "adl_playFormat", adl_playFormat))
|
||||
{
|
||||
adl_init = &adl_init_failure;
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
else
|
||||
con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic library \"%s\"", library_name);
|
||||
}
|
||||
else
|
||||
con_printf(CON_NORMAL, "ADLMIDI: loaded the dynamic OPL3 synthesizer");
|
||||
return adl_init(sample_rate);
|
||||
}
|
||||
|
||||
ADL_MIDIPlayer *(*adl_init)(long sample_rate) = &adl_init_first_call;
|
||||
void (*adl_close)(ADL_MIDIPlayer *device) = nullptr;
|
||||
int (*adl_switchEmulator)(ADL_MIDIPlayer *device, int emulator) = nullptr;
|
||||
int (*adl_setNumChips)(ADL_MIDIPlayer *device, int numChips) = nullptr;
|
||||
int (*adl_setBank)(ADL_MIDIPlayer *device, int bank) = nullptr;
|
||||
int (*adl_openBankFile)(ADL_MIDIPlayer *device, const char *filePath) = nullptr;
|
||||
void (*adl_setSoftPanEnabled)(ADL_MIDIPlayer *device, int softPanEn) = nullptr;
|
||||
void (*adl_setLoopEnabled)(ADL_MIDIPlayer *device, int loopEn) = nullptr;
|
||||
int (*adl_openData)(ADL_MIDIPlayer *device, const void *mem, unsigned long size) = nullptr;
|
||||
int (*adl_openFile)(ADL_MIDIPlayer *device, const char *filePath) = nullptr;
|
||||
int (*adl_playFormat)(ADL_MIDIPlayer *device, int sampleCount, uint8_t *left, uint8_t *right, const ADLMIDI_AudioFormat *format) = nullptr;
|
Loading…
Reference in a new issue