diff --git a/src/bindings/fluid_filerenderer.c b/src/bindings/fluid_filerenderer.c index 401daadb4..a8d521b5f 100644 --- a/src/bindings/fluid_filerenderer.c +++ b/src/bindings/fluid_filerenderer.c @@ -289,7 +289,32 @@ new_fluid_file_renderer(fluid_synth_t *synth) goto error_recovery; } +#ifdef _WIN32 + if (0 == FLUID_STRCMP("-", filename)) + dev->sndfile = sf_open(filename, SFM_WRITE, &info); // pipe open + else + { + int u16_count; + LPWSTR filename_wchar; + dev->sndfile = NULL; + + // utf-8 filename to utf-16 filename_wchar + if (1 > (u16_count = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename, -1, NULL, 0))) + FLUID_LOG(FLUID_ERR, "Failed to convert UTF8 string to wide char string"); + else if (NULL == (filename_wchar = (LPWSTR)FLUID_ARRAY(WCHAR, u16_count))) + FLUID_LOG(FLUID_ERR, "Out of memory"); + else + { + if (u16_count != MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename, -1, filename_wchar, u16_count)) + FLUID_LOG(FLUID_ERR, "Failed to convert UTF8 string to wide char string"); + else + dev->sndfile = sf_wchar_open(filename_wchar, SFM_WRITE, &info); // file open + FLUID_FREE(filename_wchar); + } + } +#else dev->sndfile = sf_open(filename, SFM_WRITE, &info); +#endif if(!dev->sndfile) { diff --git a/src/fluidsynth.c b/src/fluidsynth.c index 2b564cd12..e05ad49e9 100644 --- a/src/fluidsynth.c +++ b/src/fluidsynth.c @@ -46,9 +46,6 @@ 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 @@ -125,21 +122,11 @@ int process_o_cmd_line_option(fluid_settings_t *settings, char *optarg) break; 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) + if(fluid_settings_setstr(settings, optarg, 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: @@ -167,45 +154,6 @@ print_pretty_int(int i) } } -#ifdef _WIN32 -/* Function using win32 api to convert ANSI encoding string to UTF8 encoding string */ -static char* -win32_ansi_to_utf8(const char* ansi_null_terminated_string) -{ - LPWSTR u16_buf = NULL; - char *u8_buf = NULL; - fluid_return_val_if_fail(ansi_null_terminated_string != NULL, NULL); - do - { - int u16_count, u8_byte_count; - u16_count = MultiByteToWideChar(CP_ACP, 0, ansi_null_terminated_string, -1, NULL, 0); - if (u16_count == 0) - { - fprintf(stderr, "Failed to convert ANSI string to wide char string\n"); - break; - } - u16_buf = malloc(u16_count * sizeof(WCHAR)); - if (u16_buf == NULL) - { - fprintf(stderr, "Out of memory\n"); - break; - } - u16_count = MultiByteToWideChar(CP_ACP, 0, ansi_null_terminated_string, -1, u16_buf, u16_count); - u8_byte_count = WideCharToMultiByte(CP_UTF8, 0, u16_buf, u16_count, NULL, 0, NULL, NULL); - - u8_buf = malloc(u8_byte_count); - if (u8_buf == NULL) - { - fprintf(stderr, "Out of memory\n"); - break; - } - WideCharToMultiByte(CP_UTF8, 0, u16_buf, u16_count, u8_buf, u8_byte_count, NULL, NULL); - } while (0); - free(u16_buf); - return u8_buf; -} -#endif - typedef struct { int count; /* Total count of options */ @@ -378,7 +326,7 @@ fast_render_loop(fluid_settings_t *settings, fluid_synth_t *synth, fluid_player_ */ int main(int argc, char **argv) { - fluid_settings_t *settings; + fluid_settings_t *settings = NULL; int result = -1; int arg1 = 1; char buf[512]; @@ -404,10 +352,64 @@ int main(int argc, char **argv) static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:QqR:r:sT:Vvz:"; #ifdef _WIN32 + int argc_dup = 0; + char **argv_dup = NULL; + // console output will be utf-8 SetConsoleOutputCP(CP_UTF8); // console input, too SetConsoleCP(CP_UTF8); + + // overwrite argc and argv: utf-16 command line string to utf-8 arguments + argv = NULL; + { + LPWSTR *argv_wchar; + + // parses a unicode command line string. + if (NULL == (argv_wchar = CommandLineToArgvW(GetCommandLineW(), &argc))) + fprintf(stderr, "Failed to parses a unicode command line string\n"); + else + { + if (1 > argc) + fprintf(stderr, "Failed to parses a unicode command line string\n"); + else + { + // allocates a new argv array + if (NULL == (argv = argv_dup = (char **)malloc(sizeof(char *) * (size_t)(1 + argc)))) + fprintf(stderr, "Out of memory\n"); + else + { + argc_dup = argc; + + // initialize a new argv array + for (i = 0; argc >= i; i++) + argv[i] = NULL; + + // utf-16 to utf-8 + for (i = 0; argc > i; i++) + { + int u8_count; + + if (1 > (u8_count = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, argv_wchar[i], -1, NULL, 0, NULL, NULL))) + fprintf(stderr, "Failed to convert wide char string to UTF8 string\n"); + else if (NULL == (argv[i] = (char *)malloc(sizeof(char) * (size_t)u8_count))) + fprintf(stderr, "Out of memory\n"); + else if (u8_count != WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, argv_wchar[i], -1, argv[i], u8_count, NULL, NULL)) + fprintf(stderr, "Failed to convert wide char string to UTF8 string\n"); + else + continue; + argv = NULL; + break; + } + } + } + // release argv_wchar + LocalFree(argv_wchar); + } + } + // if failed, goto cleanup + if (NULL == argv) + goto cleanup; #endif #if SDL2_SUPPORT @@ -938,25 +940,14 @@ int main(int argc, char **argv) /* load the soundfonts (check that all non options are SoundFont or MIDI files) */ for(i = arg1; i < argc; i++) { - const char *u8_path = argv[i]; -#if defined(_WIN32) - /* try to convert ANSI encoding path to UTF8 encoding path */ - char *u8_buf = win32_ansi_to_utf8(argv[i]); - if (u8_buf == NULL) - { - // error msg. already printed - goto cleanup; - } - u8_path = u8_buf; -#endif - if(fluid_is_midifile(u8_path)) + if(fluid_is_midifile(argv[i])) { continue; } - if(fluid_is_soundfont(u8_path)) + if(fluid_is_soundfont(argv[i])) { - if(fluid_synth_sfload(synth, u8_path, 1) == -1) + if(fluid_synth_sfload(synth, argv[i], 1) == -1) { fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]); } @@ -965,9 +956,6 @@ int main(int argc, char **argv) { fprintf(stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n", argv[i]); } -#if defined(_WIN32) - free(u8_buf); -#endif } /* Try to load the default soundfont, if no soundfont specified */ @@ -1022,18 +1010,7 @@ int main(int argc, char **argv) /* create the player and add any midi files, if requested */ for(i = arg1; i < argc; i++) { - const char *u8_path = argv[i]; -#if defined(_WIN32) - /* try to convert ANSI encoding path to UTF8 encoding path */ - char *u8_buf = win32_ansi_to_utf8(argv[i]); - if (u8_buf == NULL) - { - // error msg. already printed - goto cleanup; - } - u8_path = u8_buf; -#endif - if((u8_path[0] != '-') && fluid_is_midifile(u8_path)) + if((argv[i][0] != '-') && fluid_is_midifile(argv[i])) { if(player == NULL) { @@ -1052,11 +1029,8 @@ int main(int argc, char **argv) } } - fluid_player_add(player, u8_path); + fluid_player_add(player, argv[i]); } -#if defined(_WIN32) - free(u8_buf); -#endif } /* try to load and execute the user or system configuration file */ @@ -1204,6 +1178,18 @@ int main(int argc, char **argv) delete_fluid_synth(synth); delete_fluid_settings(settings); +#ifdef _WIN32 + if (NULL != argv_dup) + { + for (i = 0; argc_dup > i; i++) + { + if (NULL != argv_dup[i]) + free(argv_dup[i]); + } + free(argv_dup); + } +#endif + return result; }