diff --git a/CMakeLists.txt b/CMakeLists.txt index 584f2e2ba..c2a8da7cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,6 +295,7 @@ if ( WIN32 OR CYGWIN ) endif() endif () message ( STATUS "Targeting Windows Version ${windows-version}" ) + add_definitions ( -D _UNICODE -D UNICODE ) add_definitions ( -D _WIN32_WINNT=${windows-version} ) add_definitions ( -D WINVER=${windows-version} ) list ( APPEND CMAKE_REQUIRED_DEFINITIONS "-DWINVER=${windows-version}" ) diff --git a/cmake_admin/PkgConfigHelpers.cmake b/cmake_admin/PkgConfigHelpers.cmake index 8c98fe3f0..4a9f87f59 100644 --- a/cmake_admin/PkgConfigHelpers.cmake +++ b/cmake_admin/PkgConfigHelpers.cmake @@ -76,7 +76,8 @@ macro ( unset_pkg_config _prefix ) endmacro ( unset_pkg_config ) function ( get_target_properties_from_pkg_config _library _prefix _out_prefix ) - if ( "${_library}" MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$" ) + if ( NOT "${_library}" MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$" + AND "${_library}" MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$" ) set ( _cflags ${_prefix}_STATIC_CFLAGS_OTHER ) set ( _link_libraries ${_prefix}_STATIC_LIBRARIES ) set ( _library_dirs ${_prefix}_STATIC_LIBRARY_DIRS ) diff --git a/doc/examples/fluidsynth_enumsettings.cxx b/doc/examples/fluidsynth_enumsettings.cxx index 8973b9de2..40599c94b 100644 --- a/doc/examples/fluidsynth_enumsettings.cxx +++ b/doc/examples/fluidsynth_enumsettings.cxx @@ -12,6 +12,10 @@ * [Pedro López-Cabanillas ] */ +#ifdef _WIN32 +#include +#endif + #include #include #include @@ -23,6 +27,11 @@ int main(int argc, char**) fluid_settings_t* settings = nullptr; void* context = nullptr; +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + setvbuf(stdout, nullptr, _IONBF, 0); +#endif + std::cout << "C++ enum settings of FluidSynth v" << fluid_version_str() << std::endl; if (argc > 1) { diff --git a/doc/fluidsettings.xml b/doc/fluidsettings.xml index c805077e4..a26beffdc 100644 --- a/doc/fluidsettings.xml +++ b/doc/fluidsettings.xml @@ -492,7 +492,7 @@ Developers: str default - Selects the DirectSound (Windows) device to use. + Selects the DirectSound (Windows) device to use. Starting with 2.3.6 all device names are expected to be UTF8 encoded. @@ -705,7 +705,7 @@ Developers: str default - Device to use for WASAPI driver output. + Device to use for WASAPI driver output. Starting with 2.3.6 all device names are expected to be UTF8 encoded. @@ -721,7 +721,7 @@ Developers: str default - Device to use for WaveOut driver output. + Device to use for WaveOut driver output. Starting with 2.3.6 all device names are expected to be UTF8 encoded. @@ -804,7 +804,7 @@ Developers: winmidi.device str default - The hardware device to use for Windows MIDI driver (not to be confused with the MIDI port). Multiple devices can be specified by a list of devices index separated by a semicolon (e.g "2;0", which is equivalent to one device with 32 MIDI channels). + The hardware device to use for Windows MIDI driver (not to be confused with the MIDI port). Multiple devices can be specified by a list of devices index separated by a semicolon (e.g "2;0", which is equivalent to one device with 32 MIDI channels). Starting with 2.3.6 all device names are expected to be UTF8 encoded. diff --git a/include/fluidsynth/settings.h b/include/fluidsynth/settings.h index 78db7dc32..45ab07a65 100644 --- a/include/fluidsynth/settings.h +++ b/include/fluidsynth/settings.h @@ -48,6 +48,9 @@ extern "C" { * // ... * } * @endcode + * All string settings are encoded in UTF-8. This includes the names + * of the audio and MIDI devices, exposed as setting options. + * * @sa @ref CreatingSettings * * @{ diff --git a/src/drivers/fluid_dsound.c b/src/drivers/fluid_dsound.c index 16fc83277..a99038b55 100644 --- a/src/drivers/fluid_dsound.c +++ b/src/drivers/fluid_dsound.c @@ -107,8 +107,18 @@ typedef struct BOOL CALLBACK fluid_dsound_enum_callback(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context) { - fluid_settings_t *settings = (fluid_settings_t *) context; - fluid_settings_add_option(settings, "audio.dsound.device", (const char *)description); + fluid_settings_t *settings = (fluid_settings_t *)context; + char *name; +#if _UNICODE + int nsz = WideCharToMultiByte(CP_UTF8, 0, description, -1, 0, 0, 0, 0); + name = FLUID_ARRAY(char, nsz); + WideCharToMultiByte(CP_UTF8, 0, description, -1, name, nsz, 0, 0); +#else + name = FLUID_STRDUP(description); +#endif + FLUID_LOG(FLUID_DBG, "adding audio.dsound.device=%s", name); + fluid_settings_add_option(settings, "audio.dsound.device", name); + FLUID_FREE(name); return TRUE; } @@ -121,11 +131,20 @@ fluid_dsound_enum_callback(LPGUID guid, LPCTSTR description, LPCTSTR module, LPV BOOL CALLBACK fluid_dsound_enum_callback2(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context) { - fluid_dsound_devsel_t *devsel = (fluid_dsound_devsel_t *) context; - FLUID_LOG(FLUID_DBG, "Testing audio device: %s", description); - - if(FLUID_STRCASECMP(devsel->devname, description) == 0) - { + fluid_dsound_devsel_t *devsel = (fluid_dsound_devsel_t *)context; + char *name; +#if _UNICODE + int nsz = WideCharToMultiByte(CP_UTF8, 0, description, -1, 0, 0, 0, 0); + name = FLUID_ARRAY(char, nsz); + WideCharToMultiByte(CP_UTF8, 0, description, -1, name, nsz, 0, 0); +#else + name = FLUID_STRDUP(description); +#endif + FLUID_LOG(FLUID_DBG, "Testing audio device: %s", name); + + if (FLUID_STRCASECMP(devsel->devname, name) == 0) + { + FLUID_FREE(name); /* The device exists, return a copy of its GUID */ devsel->devGUID = FLUID_NEW(GUID); diff --git a/src/drivers/fluid_wasapi.c b/src/drivers/fluid_wasapi.c index f94077f9d..1a933fbe0 100644 --- a/src/drivers/fluid_wasapi.c +++ b/src/drivers/fluid_wasapi.c @@ -788,9 +788,9 @@ static void fluid_wasapi_register_callback(IMMDevice *dev, void *data) int nsz; char *name; - nsz = WideCharToMultiByte(CP_ACP, 0, var.pwszVal, -1, 0, 0, 0, 0); - name = FLUID_ARRAY(char, nsz + 1); - WideCharToMultiByte(CP_ACP, 0, var.pwszVal, -1, name, nsz, 0, 0); + nsz = WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, 0, 0, 0, 0); + name = FLUID_ARRAY(char, nsz); + WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, name, nsz, 0, 0); fluid_settings_add_option(settings, "audio.wasapi.device", name); FLUID_FREE(name); } @@ -828,9 +828,9 @@ static void fluid_wasapi_finddev_callback(IMMDevice *dev, void *data) goto cleanup; } - nsz = WideCharToMultiByte(CP_ACP, 0, var.pwszVal, -1, 0, 0, 0, 0); - name = FLUID_ARRAY(char, nsz + 1); - WideCharToMultiByte(CP_ACP, 0, var.pwszVal, -1, name, nsz, 0, 0); + nsz = WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, 0, 0, 0, 0); + name = FLUID_ARRAY(char, nsz); + WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, name, nsz, 0, 0); if(!FLUID_STRCASECMP(name, d->name)) { diff --git a/src/drivers/fluid_waveout.c b/src/drivers/fluid_waveout.c index b67ead761..039295f4f 100644 --- a/src/drivers/fluid_waveout.c +++ b/src/drivers/fluid_waveout.c @@ -201,9 +201,7 @@ static DWORD WINAPI fluid_waveout_synth_thread(void *data) void fluid_waveout_audio_driver_settings(fluid_settings_t *settings) { UINT n, nDevs = waveOutGetNumDevs(); -#ifdef _UNICODE - char dev_name[MAXPNAMELEN]; -#endif + char *dev_name; fluid_settings_register_str(settings, "audio.waveout.device", "default", 0); fluid_settings_add_option(settings, "audio.waveout.device", "default"); @@ -218,13 +216,15 @@ void fluid_waveout_audio_driver_settings(fluid_settings_t *settings) if(res == MMSYSERR_NOERROR) { #ifdef _UNICODE - WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, dev_name, MAXPNAMELEN, 0, 0); - FLUID_LOG(FLUID_DBG, "Testing audio device: %s", dev_name); - fluid_settings_add_option(settings, "audio.waveout.device", dev_name); + int nsz = WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, 0, 0, 0, 0); + dev_name = FLUID_ARRAY(char, nsz); + WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, dev_name, nsz, 0, 0); #else - FLUID_LOG(FLUID_DBG, "Testing audio device: %s", caps.szPname); - fluid_settings_add_option(settings, "audio.waveout.device", caps.szPname); + dev_name = FLUID_STRDUP(caps.szPname); #endif + FLUID_LOG(FLUID_DBG, "Testing audio device: %s", dev_name); + fluid_settings_add_option(settings, "audio.waveout.device", dev_name); + FLUID_FREE(dev_name); } } } diff --git a/src/drivers/fluid_winmidi.c b/src/drivers/fluid_winmidi.c index b42edddc1..1157d7f10 100644 --- a/src/drivers/fluid_winmidi.c +++ b/src/drivers/fluid_winmidi.c @@ -229,14 +229,24 @@ fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance, * @param dev_name, name of the device. * @return the new device name (that must be freed when finish with it) or * NULL if memory allocation error. + * Note: the returned name will be encoded in UTF8 if built with _UNICODE. */ -static char *fluid_winmidi_get_device_name(int dev_idx, char *dev_name) +static char *fluid_winmidi_get_device_name(int dev_idx, TCHAR *input_dev_name) { char *new_dev_name; + char *dev_name; int i = dev_idx; size_t size = 0; /* index size */ +#if _UNICODE + int nsz = WideCharToMultiByte(CP_UTF8, 0, input_dev_name, -1, 0, 0, 0, 0); + dev_name = FLUID_ARRAY(char, nsz); + WideCharToMultiByte(CP_UTF8, 0, input_dev_name, -1, dev_name, nsz, 0, 0); +#else + dev_name = FLUID_STRDUP(input_dev_name); +#endif + do { size++; @@ -256,6 +266,7 @@ static char *fluid_winmidi_get_device_name(int dev_idx, char *dev_name) { FLUID_LOG(FLUID_ERR, "Out of memory"); } + FLUID_FREE(dev_name); return new_dev_name; } @@ -429,14 +440,7 @@ fluid_winmidi_parse_device_name(fluid_winmidi_driver_t *dev, char *dev_name) break; } -#ifdef _UNICODE - WCHAR wDevName[MAXPNAMELEN]; - MultiByteToWideChar(CP_UTF8, 0, dev_name, -1, wDevName, MAXPNAMELEN); - - str_cmp_res = wcsicmp(wDevName, new_dev_name); -#else str_cmp_res = FLUID_STRCASECMP(dev_name, new_dev_name); -#endif FLUID_LOG(FLUID_DBG, "Testing midi device \"%s\"", new_dev_name); FLUID_FREE(new_dev_name); diff --git a/src/fluidsynth.c b/src/fluidsynth.c index 11c917dfe..f08fa96e2 100644 --- a/src/fluidsynth.c +++ b/src/fluidsynth.c @@ -46,6 +46,9 @@ void print_help(fluid_settings_t *settings); void print_welcome(void); void print_configure(void); void fluid_wasapi_device_enumerate(void); +#ifdef _WIN32 +static char* win32_ansi_to_utf8(const char* ansi_null_terminated_string); +#endif /* * the globals @@ -120,16 +123,25 @@ int process_o_cmd_line_option(fluid_settings_t *settings, char *optarg) } break; - - case FLUID_STR_TYPE: - if(fluid_settings_setstr(settings, optarg, val) != FLUID_OK) + + case FLUID_STR_TYPE: { + char *u8_val = val; +#if defined(_WIN32) + u8_val = win32_ansi_to_utf8(val); +#endif + if(fluid_settings_setstr(settings, optarg, u8_val) != FLUID_OK) { fprintf(stderr, "Failed to set string parameter '%s'\n", optarg); +#if defined(_WIN32) + free(u8_val); +#endif return FLUID_FAILED; } - +#if defined(_WIN32) + free(u8_val); +#endif break; - + } default: fprintf(stderr, "Setting parameter '%s' not found\n", optarg); return FLUID_FAILED; @@ -391,6 +403,13 @@ int main(int argc, char **argv) int fast_render = 0; static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:QqR:r:sT:Vvz:"; +#ifdef _WIN32 + // console output will be utf-8 + SetConsoleOutputCP(CP_UTF8); + // console input, too + SetConsoleCP(CP_UTF8); +#endif + #if SDL2_SUPPORT // Tell SDL that it shouldn't intercept signals, otherwise SIGINT and SIGTERM won't quit fluidsynth SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");