/* * This file is part of the DXX-Rebirth project . * 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 #else #include #endif namespace { #if defined(_WIN32) enum { RTLD_LAZY = 1, RTLD_NOW = 2 }; HMODULE dlopen(const char *const filename, int) { return LoadLibraryA(filename); } void dlclose(const HMODULE handle) { FreeLibrary(handle); } void *dlsym(const HMODULE handle, const char *const symbol) { return reinterpret_cast( GetProcAddress(handle, symbol)); } #else using HMODULE = void *; #endif } static ADL_MIDIPlayer *adl_init_failure(long) { return nullptr; } static void reported_failed_load_function(const char *const name) { con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic function \"%s\"", name); } template static bool load_function(const HMODULE handle, const char *const name, F *&fptr) { const auto f = reinterpret_cast(dlsym(handle, name)); fptr = f; if (!f) /* Use out of line report function to prevent redundant instantiations * on a per-type basis. */ reported_failed_load_function(name); return f; } 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 const auto handle = dlopen(library_name, RTLD_NOW); 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_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); int (*adl_switchEmulator)(ADL_MIDIPlayer *device, int emulator); int (*adl_setNumChips)(ADL_MIDIPlayer *device, int numChips); int (*adl_setBank)(ADL_MIDIPlayer *device, int bank); void (*adl_setSoftPanEnabled)(ADL_MIDIPlayer *device, int softPanEn); void (*adl_setLoopEnabled)(ADL_MIDIPlayer *device, int loopEn); int (*adl_openData)(ADL_MIDIPlayer *device, const void *mem, unsigned long size); int (*adl_openFile)(ADL_MIDIPlayer *device, const char *filePath); int (*adl_playFormat)(ADL_MIDIPlayer *device, int sampleCount, uint8_t *left, uint8_t *right, const ADLMIDI_AudioFormat *format);