Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
3
 * It is copyright by its individual contributors, as recorded in the
4
 * project's Git history.  See COPYING.txt at the top level for license
5
 * terms and a link to the Git history.
6
 */
7
/*
8
 * This is a dynamic interface to libADLMIDI, the OPL3 synthesizer library.
9
 */
10
 
11
#include "adlmidi_dynamic.h"
12
#include "console.h"
13
#if !defined(_WIN32)
14
#include <dlfcn.h>
15
#else
16
#include <windows.h>
17
#endif
18
 
19
namespace {
20
 
21
#if defined(_WIN32)
22
enum
23
{
24
        RTLD_LAZY = 1, RTLD_NOW = 2
25
};
26
 
27
HMODULE dlopen(const char *const filename, int)
28
{
29
        return LoadLibraryA(filename);
30
}
31
 
32
void dlclose(const HMODULE handle)
33
{
34
        FreeLibrary(handle);
35
}
36
 
37
void *dlsym(const HMODULE handle, const char *const symbol)
38
{
39
        return reinterpret_cast<void *>(
40
                GetProcAddress(handle, symbol));
41
}
42
#else
43
using HMODULE = void *;
44
#endif
45
 
46
}
47
 
48
static ADL_MIDIPlayer *adl_init_failure(long)
49
{
50
        return nullptr;
51
}
52
 
53
static void reported_failed_load_function(const char *const name)
54
{
55
        con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic function \"%s\"", name);
56
}
57
 
58
template <class F>
59
static bool load_function(const HMODULE handle, const char *const name, F *&fptr)
60
{
61
        const auto f = reinterpret_cast<F *>(dlsym(handle, name));
62
        fptr = f;
63
        if (!f)
64
                /* Use out of line report function to prevent redundant instantiations
65
                 * on a per-type basis.
66
                 */
67
                reported_failed_load_function(name);
68
        return f;
69
}
70
 
71
static ADL_MIDIPlayer *adl_init_first_call(long sample_rate)
72
{
73
#if defined(_WIN32)
74
        const char *library_name = "libADLMIDI.dll";
75
#elif defined(__APPLE__)
76
        const char *library_name = "libADLMIDI.dylib";
77
#else
78
        const char *library_name = "libADLMIDI.so";
79
#endif
80
        const auto handle = dlopen(library_name, RTLD_NOW);
81
        if (!handle ||
82
            !load_function(handle, "adl_init", adl_init) ||
83
            !load_function(handle, "adl_close", adl_close) ||
84
            !load_function(handle, "adl_switchEmulator", adl_switchEmulator) ||
85
            !load_function(handle, "adl_setNumChips", adl_setNumChips) ||
86
            !load_function(handle, "adl_setBank", adl_setBank) ||
87
            !load_function(handle, "adl_setSoftPanEnabled", adl_setSoftPanEnabled) ||
88
            !load_function(handle, "adl_setLoopEnabled", adl_setLoopEnabled) ||
89
            !load_function(handle, "adl_openData", adl_openData) ||
90
            !load_function(handle, "adl_openFile", adl_openFile) ||
91
            !load_function(handle, "adl_playFormat", adl_playFormat))
92
        {
93
                adl_init = &adl_init_failure;
94
                if (handle)
95
                        dlclose(handle);
96
                else
97
                        con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic library \"%s\"", library_name);
98
        }
99
        else
100
                con_printf(CON_NORMAL, "ADLMIDI: loaded the dynamic OPL3 synthesizer");
101
        return adl_init(sample_rate);
102
}
103
 
104
ADL_MIDIPlayer *(*adl_init)(long sample_rate) = &adl_init_first_call;
105
void (*adl_close)(ADL_MIDIPlayer *device);
106
int (*adl_switchEmulator)(ADL_MIDIPlayer *device, int emulator);
107
int (*adl_setNumChips)(ADL_MIDIPlayer *device, int numChips);
108
int (*adl_setBank)(ADL_MIDIPlayer *device, int bank);
109
void (*adl_setSoftPanEnabled)(ADL_MIDIPlayer *device, int softPanEn);
110
void (*adl_setLoopEnabled)(ADL_MIDIPlayer *device, int loopEn);
111
int (*adl_openData)(ADL_MIDIPlayer *device, const void *mem, unsigned long size);
112
int (*adl_openFile)(ADL_MIDIPlayer *device, const char *filePath);
113
int (*adl_playFormat)(ADL_MIDIPlayer *device, int sampleCount, uint8_t *left, uint8_t *right, const ADLMIDI_AudioFormat *format);