Skip to content

Commit

Permalink
Merge pull request #1421 from pedrolcl/windows_unicode_commandline
Browse files Browse the repository at this point in the history
Convert fluidsynth CLI arguments
  • Loading branch information
derselbst authored Nov 6, 2024
2 parents 0a86368 + 0506f3b commit 91beec4
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 79 deletions.
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ if ( TARGET PipeWire::PipeWire AND PIPEWIRE_SUPPORT ) # because pw_init() etc.
target_link_libraries ( fluidsynth PRIVATE PipeWire::PipeWire )
endif()

if ( MINGW )
target_link_options( fluidsynth PRIVATE -municode )
endif()

if ( MACOSX_FRAMEWORK )
install ( TARGETS fluidsynth libfluidsynth
EXPORT FluidSynthTargets
Expand Down
125 changes: 46 additions & 79 deletions src/fluidsynth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -126,20 +123,11 @@ int process_o_cmd_line_option(fluid_settings_t *settings, char *optarg)

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:
Expand Down Expand Up @@ -167,45 +155,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 */
Expand Down Expand Up @@ -376,9 +325,13 @@ fast_render_loop(fluid_settings_t *settings, fluid_synth_t *synth, fluid_player_
15)create the audio driver (i.e synthesis thread) and a synchronous user
shell if interactive.
*/
#if defined(_WIN32)
int wmain(int argc, wchar_t **wargv)
#else
int main(int argc, char **argv)
#endif
{
fluid_settings_t *settings;
fluid_settings_t *settings = NULL;
int result = -1;
int arg1 = 1;
char buf[512];
Expand All @@ -403,11 +356,40 @@ 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
#if defined(_WIN32)
char **argv = NULL;
// console output will be utf-8
SetConsoleOutputCP(CP_UTF8);
// console input, too
SetConsoleCP(CP_UTF8);
// conversion of wchar_t (UTF-16) arguments to char (UTF-8)
if ((argv = (char **) calloc( argc, sizeof(char *) )) == NULL)
{
fprintf(stderr, "Out of memory\n");
goto cleanup;
}
else
{
for (i = 0; i < argc; ++i)
{
int u8_count = 0;
if (1 > (u8_count = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wargv[i], -1, NULL, 0, NULL, NULL)))
{
fprintf(stderr, "Failed to convert wide char string to UTF8\n");
goto cleanup;
}
else if ((argv[i] = (char *) calloc(u8_count, sizeof(char))) == NULL)
{
fprintf(stderr, "Out of memory\n");
goto cleanup;
}
else if (u8_count != WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wargv[i], -1, argv[i], u8_count, NULL, NULL))
{
fprintf(stderr, "Failed to convert wide char string to UTF8\n");
goto cleanup;
}
}
}
#endif

#if SDL2_SUPPORT
Expand Down Expand Up @@ -939,16 +921,6 @@ int main(int argc, char **argv)
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))
{
continue;
Expand All @@ -965,9 +937,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 */
Expand Down Expand Up @@ -1023,16 +992,6 @@ int main(int argc, char **argv)
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(player == NULL)
Expand All @@ -1054,9 +1013,6 @@ int main(int argc, char **argv)

fluid_player_add(player, u8_path);
}
#if defined(_WIN32)
free(u8_buf);
#endif
}

/* try to load and execute the user or system configuration file */
Expand Down Expand Up @@ -1204,6 +1160,17 @@ int main(int argc, char **argv)
delete_fluid_synth(synth);
delete_fluid_settings(settings);

#ifdef _WIN32
if (argv != NULL)
{
for (i = 0; i < argc; ++i)
{
free(argv[i]);
}
free(argv);
}
#endif

return result;
}

Expand Down

0 comments on commit 91beec4

Please sign in to comment.