diff --git a/bottles/frontend/cli.py b/bottles/frontend/cli.py index d6211929f72..4008ec9e3a6 100644 --- a/bottles/frontend/cli.py +++ b/bottles/frontend/cli.py @@ -670,6 +670,7 @@ def run_program(self): program.get("pre_script", None) program.get("post_script", None) program.get("folder", None) + program.get("midi_soundfont", None) program.get("dxvk") program.get("vkd3d") diff --git a/bottles/frontend/filters.py b/bottles/frontend/filters.py index 509bd850e0b..58b19690371 100644 --- a/bottles/frontend/filters.py +++ b/bottles/frontend/filters.py @@ -27,6 +27,10 @@ def add_executable_filters(dialog): __set_filter(dialog, _("Supported Executables"), ["*.exe", "*.msi"]) +def add_soundfont_filters(dialog): + __set_filter(dialog, _("Supported SoundFonts"), ["*.sf2", "*.sf3"]) + + def add_yaml_filters(dialog): # TODO: Investigate why `filter.add_mime_type(...)` does not show filter in all distributions. # Intended MIME types are: diff --git a/bottles/frontend/launch-options-dialog.blp b/bottles/frontend/launch-options-dialog.blp index ebd35d227ec..e107cab0221 100644 --- a/bottles/frontend/launch-options-dialog.blp +++ b/bottles/frontend/launch-options-dialog.blp @@ -140,6 +140,37 @@ template $LaunchOptionsDialog: Adw.Window { } } } + + Adw.ActionRow action_midi_soundfont { + activatable-widget: btn_midi_soundfont; + title: _("MIDI SoundFont"); + subtitle: _("Choose a custom SoundFont for MIDI playback."); + + Box { + spacing: 6; + + Button btn_midi_soundfont_reset { + tooltip-text: _("Reset to Default"); + valign: center; + visible: false; + icon-name: "edit-undo-symbolic"; + + styles [ + "flat", + ] + } + + Button btn_midi_soundfont { + tooltip-text: _("Choose a SoundFont"); + valign: center; + icon-name: "document-open-symbolic"; + + styles [ + "flat", + ] + } + } + } } Adw.PreferencesGroup { diff --git a/bottles/frontend/launch_options_dialog.py b/bottles/frontend/launch_options_dialog.py index 2fbbbc95944..97c4dc9b25b 100644 --- a/bottles/frontend/launch_options_dialog.py +++ b/bottles/frontend/launch_options_dialog.py @@ -19,6 +19,7 @@ from bottles.backend.utils.manager import ManagerUtils from bottles.backend.logger import Logger +from bottles.frontend.filters import add_all_filters, add_soundfont_filters from gettext import gettext as _ logging = Logger() @@ -40,9 +41,12 @@ class LaunchOptionsDialog(Adw.Window): btn_post_script_reset = Gtk.Template.Child() btn_cwd = Gtk.Template.Child() btn_cwd_reset = Gtk.Template.Child() + btn_midi_soundfont = Gtk.Template.Child() + btn_midi_soundfont_reset = Gtk.Template.Child() btn_reset_defaults = Gtk.Template.Child() action_pre_script = Gtk.Template.Child() action_post_script = Gtk.Template.Child() + action_midi_soundfont = Gtk.Template.Child() switch_dxvk = Gtk.Template.Child() switch_vkd3d = Gtk.Template.Child() switch_nvapi = Gtk.Template.Child() @@ -61,6 +65,7 @@ class LaunchOptionsDialog(Adw.Window): __default_pre_script_msg = _("Choose a script which should be executed before run.") __default_post_script_msg = _("Choose a script which should be executed after run.") __default_cwd_msg = _("Choose from where start the program.") + __default_midi_soundfont_msg = _("Choose a custom SoundFont for MIDI playback.") __msg_disabled = _("{0} is disabled globally for this bottle.") __msg_override = _("This setting overrides the bottle's global setting.") @@ -106,6 +111,8 @@ def __init__(self, parent, config, program, **kwargs): self.btn_pre_script_reset.connect("clicked", self.__reset_pre_script) self.btn_post_script.connect("clicked", self.__choose_post_script) self.btn_post_script_reset.connect("clicked", self.__reset_post_script) + self.btn_midi_soundfont.connect("clicked", self.__choose_midi_soundfont) + self.btn_midi_soundfont_reset.connect("clicked", self.__reset_midi_soundfont) self.btn_cwd.connect("clicked", self.__choose_cwd) self.btn_cwd_reset.connect("clicked", self.__reset_cwd) self.btn_reset_defaults.connect("clicked", self.__reset_defaults) @@ -185,6 +192,10 @@ def __init__(self, parent, config, program, **kwargs): self.action_cwd.set_subtitle(program["folder"]) self.btn_cwd_reset.set_visible(True) + if program.get("midi_soundfont") not in ["", None]: + self.action_midi_soundfont.set_subtitle(program["midi_soundfont"]) + self.btn_midi_soundfont_reset.set_visible(True) + self.__set_disabled_switches() def __check_override(self, widget, state, action, name): @@ -344,6 +355,47 @@ def __reset_cwd(self, *_args): self.action_cwd.set_subtitle(self.__default_cwd_msg) self.btn_cwd_reset.set_visible(False) + def __choose_midi_soundfont(self, *_args): + def set_path(dialog, result): + try: + file = dialog.open_finish(result) + if file is None: + self.action_midi_soundfont.set_subtitle( + self.__default_midi_soundfont_msg + ) + return + + file_path = file.get_path() + self.program["midi_soundfont"] = file_path + self.action_midi_soundfont.set_subtitle(file_path) + self.btn_midi_soundfont_reset.set_visible(True) + + except GLib.Error as error: + # also thrown when dialog has been cancelled + if error.code == 2: + # error 2 seems to be 'dismiss' or 'cancel' + if self.program["midi_soundfont"] in (None, ""): + self.action_midi_soundfont.set_subtitle( + self.__default_midi_soundfont_msg + ) + else: + # something else happened... + logging.warning("Error selecting SoundFont file: %s" % error) + + dialog = Gtk.FileDialog.new() + dialog.set_title(_("Select MIDI SoundFont")) + dialog.set_modal(True) + + add_soundfont_filters(dialog) + add_all_filters(dialog) + + dialog.open(parent=self.window, callback=set_path) + + def __reset_midi_soundfont(self, *_args): + self.program["midi_soundfont"] = None + self.action_midi_soundfont.set_subtitle(self.__default_midi_soundfont_msg) + self.btn_midi_soundfont_reset.set_visible(False) + def __reset_defaults(self, *_args): self.switch_dxvk.set_active(self.global_dxvk) self.switch_vkd3d.set_active(self.global_vkd3d)