bauiv1lib.settings.audio

Provides audio settings UI.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides audio settings UI."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8import logging
  9
 10import bauiv1 as bui
 11
 12if TYPE_CHECKING:
 13    pass
 14
 15
 16class AudioSettingsWindow(bui.Window):
 17    """Window for editing audio settings."""
 18
 19    def __init__(
 20        self,
 21        transition: str = 'in_right',
 22        origin_widget: bui.Widget | None = None,
 23    ):
 24        # pylint: disable=too-many-statements
 25        # pylint: disable=too-many-locals
 26        # pylint: disable=cyclic-import
 27        from bauiv1lib.popup import PopupMenu
 28        from bauiv1lib.config import ConfigNumberEdit
 29
 30        assert bui.app.classic is not None
 31        music = bui.app.classic.music
 32
 33        # If they provided an origin-widget, scale up from that.
 34        scale_origin: tuple[float, float] | None
 35        if origin_widget is not None:
 36            self._transition_out = 'out_scale'
 37            scale_origin = origin_widget.get_screen_space_center()
 38            transition = 'in_scale'
 39        else:
 40            self._transition_out = 'out_right'
 41            scale_origin = None
 42
 43        self._r = 'audioSettingsWindow'
 44
 45        spacing = 50.0
 46        width = 460.0
 47        height = 210.0
 48
 49        # Update: hard-coding head-relative audio to true now,
 50        # so not showing options.
 51        # show_vr_head_relative_audio = True if bui.app.vr_mode else False
 52        show_vr_head_relative_audio = False
 53
 54        if show_vr_head_relative_audio:
 55            height += 70
 56
 57        show_soundtracks = False
 58        if music.have_music_player():
 59            show_soundtracks = True
 60            height += spacing * 2.0
 61
 62        uiscale = bui.app.ui_v1.uiscale
 63        base_scale = (
 64            2.05
 65            if uiscale is bui.UIScale.SMALL
 66            else 1.6
 67            if uiscale is bui.UIScale.MEDIUM
 68            else 1.0
 69        )
 70        popup_menu_scale = base_scale * 1.2
 71
 72        super().__init__(
 73            root_widget=bui.containerwidget(
 74                size=(width, height),
 75                transition=transition,
 76                scale=base_scale,
 77                scale_origin_stack_offset=scale_origin,
 78                stack_offset=(0, -20)
 79                if uiscale is bui.UIScale.SMALL
 80                else (0, 0),
 81            )
 82        )
 83
 84        self._back_button = back_button = btn = bui.buttonwidget(
 85            parent=self._root_widget,
 86            position=(35, height - 55),
 87            size=(120, 60),
 88            scale=0.8,
 89            text_scale=1.2,
 90            label=bui.Lstr(resource='backText'),
 91            button_type='back',
 92            on_activate_call=self._back,
 93            autoselect=True,
 94        )
 95        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 96        v = height - 60
 97        v -= spacing * 1.0
 98        bui.textwidget(
 99            parent=self._root_widget,
100            position=(width * 0.5, height - 32),
101            size=(0, 0),
102            text=bui.Lstr(resource=self._r + '.titleText'),
103            color=bui.app.ui_v1.title_color,
104            maxwidth=180,
105            h_align='center',
106            v_align='center',
107        )
108
109        bui.buttonwidget(
110            edit=self._back_button,
111            button_type='backSmall',
112            size=(60, 60),
113            label=bui.charstr(bui.SpecialChar.BACK),
114        )
115
116        self._sound_volume_numedit = svne = ConfigNumberEdit(
117            parent=self._root_widget,
118            position=(40, v),
119            xoffset=10,
120            configkey='Sound Volume',
121            displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
122            minval=0.0,
123            maxval=1.0,
124            increment=0.1,
125        )
126        if bui.app.ui_v1.use_toolbars:
127            bui.widget(
128                edit=svne.plusbutton,
129                right_widget=bui.get_special_widget('party_button'),
130            )
131        v -= spacing
132        self._music_volume_numedit = ConfigNumberEdit(
133            parent=self._root_widget,
134            position=(40, v),
135            xoffset=10,
136            configkey='Music Volume',
137            displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
138            minval=0.0,
139            maxval=1.0,
140            increment=0.1,
141            callback=music.music_volume_changed,
142            changesound=False,
143        )
144
145        v -= 0.5 * spacing
146
147        self._vr_head_relative_audio_button: bui.Widget | None
148        if show_vr_head_relative_audio:
149            v -= 40
150            bui.textwidget(
151                parent=self._root_widget,
152                position=(40, v + 24),
153                size=(0, 0),
154                text=bui.Lstr(resource=self._r + '.headRelativeVRAudioText'),
155                color=(0.8, 0.8, 0.8),
156                maxwidth=230,
157                h_align='left',
158                v_align='center',
159            )
160
161            popup = PopupMenu(
162                parent=self._root_widget,
163                position=(290, v),
164                width=120,
165                button_size=(135, 50),
166                scale=popup_menu_scale,
167                choices=['Auto', 'On', 'Off'],
168                choices_display=[
169                    bui.Lstr(resource='autoText'),
170                    bui.Lstr(resource='onText'),
171                    bui.Lstr(resource='offText'),
172                ],
173                current_choice=bui.app.config.resolve('VR Head Relative Audio'),
174                on_value_change_call=self._set_vr_head_relative_audio,
175            )
176            self._vr_head_relative_audio_button = popup.get_button()
177            bui.textwidget(
178                parent=self._root_widget,
179                position=(width * 0.5, v - 11),
180                size=(0, 0),
181                text=bui.Lstr(
182                    resource=self._r + '.headRelativeVRAudioInfoText'
183                ),
184                scale=0.5,
185                color=(0.7, 0.8, 0.7),
186                maxwidth=400,
187                flatness=1.0,
188                h_align='center',
189                v_align='center',
190            )
191            v -= 30
192        else:
193            self._vr_head_relative_audio_button = None
194
195        self._soundtrack_button: bui.Widget | None
196        if show_soundtracks:
197            v -= 1.2 * spacing
198            self._soundtrack_button = bui.buttonwidget(
199                parent=self._root_widget,
200                position=((width - 310) / 2, v),
201                size=(310, 50),
202                autoselect=True,
203                label=bui.Lstr(resource=self._r + '.soundtrackButtonText'),
204                on_activate_call=self._do_soundtracks,
205            )
206            v -= spacing * 0.5
207            bui.textwidget(
208                parent=self._root_widget,
209                position=(0, v),
210                size=(width, 20),
211                text=bui.Lstr(resource=self._r + '.soundtrackDescriptionText'),
212                flatness=1.0,
213                h_align='center',
214                scale=0.5,
215                color=(0.7, 0.8, 0.7, 1.0),
216                maxwidth=400,
217            )
218        else:
219            self._soundtrack_button = None
220
221        # Tweak a few navigation bits.
222        try:
223            bui.widget(edit=back_button, down_widget=svne.minusbutton)
224        except Exception:
225            logging.exception('Error wiring AudioSettingsWindow.')
226
227        self._restore_state()
228
229    def _set_vr_head_relative_audio(self, val: str) -> None:
230        cfg = bui.app.config
231        cfg['VR Head Relative Audio'] = val
232        cfg.apply_and_commit()
233
234    def _do_soundtracks(self) -> None:
235        # pylint: disable=cyclic-import
236        from bauiv1lib.soundtrack import browser as stb
237
238        # We require disk access for soundtracks;
239        # if we don't have it, request it.
240        if not bui.have_permission(bui.Permission.STORAGE):
241            bui.getsound('ding').play()
242            bui.screenmessage(
243                bui.Lstr(resource='storagePermissionAccessText'),
244                color=(0.5, 1, 0.5),
245            )
246            bui.apptimer(
247                1.0, bui.Call(bui.request_permission, bui.Permission.STORAGE)
248            )
249            return
250
251        self._save_state()
252        bui.containerwidget(edit=self._root_widget, transition='out_left')
253        assert bui.app.classic is not None
254        bui.app.ui_v1.set_main_menu_window(
255            stb.SoundtrackBrowserWindow(
256                origin_widget=self._soundtrack_button
257            ).get_root_widget()
258        )
259
260    def _back(self) -> None:
261        # pylint: disable=cyclic-import
262        from bauiv1lib.settings import allsettings
263
264        self._save_state()
265        bui.containerwidget(
266            edit=self._root_widget, transition=self._transition_out
267        )
268        assert bui.app.classic is not None
269        bui.app.ui_v1.set_main_menu_window(
270            allsettings.AllSettingsWindow(
271                transition='in_left'
272            ).get_root_widget()
273        )
274
275    def _save_state(self) -> None:
276        try:
277            sel = self._root_widget.get_selected_child()
278            if sel == self._sound_volume_numedit.minusbutton:
279                sel_name = 'SoundMinus'
280            elif sel == self._sound_volume_numedit.plusbutton:
281                sel_name = 'SoundPlus'
282            elif sel == self._music_volume_numedit.minusbutton:
283                sel_name = 'MusicMinus'
284            elif sel == self._music_volume_numedit.plusbutton:
285                sel_name = 'MusicPlus'
286            elif sel == self._soundtrack_button:
287                sel_name = 'Soundtrack'
288            elif sel == self._back_button:
289                sel_name = 'Back'
290            elif sel == self._vr_head_relative_audio_button:
291                sel_name = 'VRHeadRelative'
292            else:
293                raise ValueError(f'unrecognized selection \'{sel}\'')
294            assert bui.app.classic is not None
295            bui.app.ui_v1.window_states[type(self)] = sel_name
296        except Exception:
297            logging.exception('Error saving state for %s.', self)
298
299    def _restore_state(self) -> None:
300        try:
301            assert bui.app.classic is not None
302            sel_name = bui.app.ui_v1.window_states.get(type(self))
303            sel: bui.Widget | None
304            if sel_name == 'SoundMinus':
305                sel = self._sound_volume_numedit.minusbutton
306            elif sel_name == 'SoundPlus':
307                sel = self._sound_volume_numedit.plusbutton
308            elif sel_name == 'MusicMinus':
309                sel = self._music_volume_numedit.minusbutton
310            elif sel_name == 'MusicPlus':
311                sel = self._music_volume_numedit.plusbutton
312            elif sel_name == 'VRHeadRelative':
313                sel = self._vr_head_relative_audio_button
314            elif sel_name == 'Soundtrack':
315                sel = self._soundtrack_button
316            elif sel_name == 'Back':
317                sel = self._back_button
318            else:
319                sel = self._back_button
320            if sel:
321                bui.containerwidget(edit=self._root_widget, selected_child=sel)
322        except Exception:
323            logging.exception('Error restoring state for %s.', self)
class AudioSettingsWindow(bauiv1._uitypes.Window):
 17class AudioSettingsWindow(bui.Window):
 18    """Window for editing audio settings."""
 19
 20    def __init__(
 21        self,
 22        transition: str = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27        # pylint: disable=cyclic-import
 28        from bauiv1lib.popup import PopupMenu
 29        from bauiv1lib.config import ConfigNumberEdit
 30
 31        assert bui.app.classic is not None
 32        music = bui.app.classic.music
 33
 34        # If they provided an origin-widget, scale up from that.
 35        scale_origin: tuple[float, float] | None
 36        if origin_widget is not None:
 37            self._transition_out = 'out_scale'
 38            scale_origin = origin_widget.get_screen_space_center()
 39            transition = 'in_scale'
 40        else:
 41            self._transition_out = 'out_right'
 42            scale_origin = None
 43
 44        self._r = 'audioSettingsWindow'
 45
 46        spacing = 50.0
 47        width = 460.0
 48        height = 210.0
 49
 50        # Update: hard-coding head-relative audio to true now,
 51        # so not showing options.
 52        # show_vr_head_relative_audio = True if bui.app.vr_mode else False
 53        show_vr_head_relative_audio = False
 54
 55        if show_vr_head_relative_audio:
 56            height += 70
 57
 58        show_soundtracks = False
 59        if music.have_music_player():
 60            show_soundtracks = True
 61            height += spacing * 2.0
 62
 63        uiscale = bui.app.ui_v1.uiscale
 64        base_scale = (
 65            2.05
 66            if uiscale is bui.UIScale.SMALL
 67            else 1.6
 68            if uiscale is bui.UIScale.MEDIUM
 69            else 1.0
 70        )
 71        popup_menu_scale = base_scale * 1.2
 72
 73        super().__init__(
 74            root_widget=bui.containerwidget(
 75                size=(width, height),
 76                transition=transition,
 77                scale=base_scale,
 78                scale_origin_stack_offset=scale_origin,
 79                stack_offset=(0, -20)
 80                if uiscale is bui.UIScale.SMALL
 81                else (0, 0),
 82            )
 83        )
 84
 85        self._back_button = back_button = btn = bui.buttonwidget(
 86            parent=self._root_widget,
 87            position=(35, height - 55),
 88            size=(120, 60),
 89            scale=0.8,
 90            text_scale=1.2,
 91            label=bui.Lstr(resource='backText'),
 92            button_type='back',
 93            on_activate_call=self._back,
 94            autoselect=True,
 95        )
 96        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 97        v = height - 60
 98        v -= spacing * 1.0
 99        bui.textwidget(
100            parent=self._root_widget,
101            position=(width * 0.5, height - 32),
102            size=(0, 0),
103            text=bui.Lstr(resource=self._r + '.titleText'),
104            color=bui.app.ui_v1.title_color,
105            maxwidth=180,
106            h_align='center',
107            v_align='center',
108        )
109
110        bui.buttonwidget(
111            edit=self._back_button,
112            button_type='backSmall',
113            size=(60, 60),
114            label=bui.charstr(bui.SpecialChar.BACK),
115        )
116
117        self._sound_volume_numedit = svne = ConfigNumberEdit(
118            parent=self._root_widget,
119            position=(40, v),
120            xoffset=10,
121            configkey='Sound Volume',
122            displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
123            minval=0.0,
124            maxval=1.0,
125            increment=0.1,
126        )
127        if bui.app.ui_v1.use_toolbars:
128            bui.widget(
129                edit=svne.plusbutton,
130                right_widget=bui.get_special_widget('party_button'),
131            )
132        v -= spacing
133        self._music_volume_numedit = ConfigNumberEdit(
134            parent=self._root_widget,
135            position=(40, v),
136            xoffset=10,
137            configkey='Music Volume',
138            displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
139            minval=0.0,
140            maxval=1.0,
141            increment=0.1,
142            callback=music.music_volume_changed,
143            changesound=False,
144        )
145
146        v -= 0.5 * spacing
147
148        self._vr_head_relative_audio_button: bui.Widget | None
149        if show_vr_head_relative_audio:
150            v -= 40
151            bui.textwidget(
152                parent=self._root_widget,
153                position=(40, v + 24),
154                size=(0, 0),
155                text=bui.Lstr(resource=self._r + '.headRelativeVRAudioText'),
156                color=(0.8, 0.8, 0.8),
157                maxwidth=230,
158                h_align='left',
159                v_align='center',
160            )
161
162            popup = PopupMenu(
163                parent=self._root_widget,
164                position=(290, v),
165                width=120,
166                button_size=(135, 50),
167                scale=popup_menu_scale,
168                choices=['Auto', 'On', 'Off'],
169                choices_display=[
170                    bui.Lstr(resource='autoText'),
171                    bui.Lstr(resource='onText'),
172                    bui.Lstr(resource='offText'),
173                ],
174                current_choice=bui.app.config.resolve('VR Head Relative Audio'),
175                on_value_change_call=self._set_vr_head_relative_audio,
176            )
177            self._vr_head_relative_audio_button = popup.get_button()
178            bui.textwidget(
179                parent=self._root_widget,
180                position=(width * 0.5, v - 11),
181                size=(0, 0),
182                text=bui.Lstr(
183                    resource=self._r + '.headRelativeVRAudioInfoText'
184                ),
185                scale=0.5,
186                color=(0.7, 0.8, 0.7),
187                maxwidth=400,
188                flatness=1.0,
189                h_align='center',
190                v_align='center',
191            )
192            v -= 30
193        else:
194            self._vr_head_relative_audio_button = None
195
196        self._soundtrack_button: bui.Widget | None
197        if show_soundtracks:
198            v -= 1.2 * spacing
199            self._soundtrack_button = bui.buttonwidget(
200                parent=self._root_widget,
201                position=((width - 310) / 2, v),
202                size=(310, 50),
203                autoselect=True,
204                label=bui.Lstr(resource=self._r + '.soundtrackButtonText'),
205                on_activate_call=self._do_soundtracks,
206            )
207            v -= spacing * 0.5
208            bui.textwidget(
209                parent=self._root_widget,
210                position=(0, v),
211                size=(width, 20),
212                text=bui.Lstr(resource=self._r + '.soundtrackDescriptionText'),
213                flatness=1.0,
214                h_align='center',
215                scale=0.5,
216                color=(0.7, 0.8, 0.7, 1.0),
217                maxwidth=400,
218            )
219        else:
220            self._soundtrack_button = None
221
222        # Tweak a few navigation bits.
223        try:
224            bui.widget(edit=back_button, down_widget=svne.minusbutton)
225        except Exception:
226            logging.exception('Error wiring AudioSettingsWindow.')
227
228        self._restore_state()
229
230    def _set_vr_head_relative_audio(self, val: str) -> None:
231        cfg = bui.app.config
232        cfg['VR Head Relative Audio'] = val
233        cfg.apply_and_commit()
234
235    def _do_soundtracks(self) -> None:
236        # pylint: disable=cyclic-import
237        from bauiv1lib.soundtrack import browser as stb
238
239        # We require disk access for soundtracks;
240        # if we don't have it, request it.
241        if not bui.have_permission(bui.Permission.STORAGE):
242            bui.getsound('ding').play()
243            bui.screenmessage(
244                bui.Lstr(resource='storagePermissionAccessText'),
245                color=(0.5, 1, 0.5),
246            )
247            bui.apptimer(
248                1.0, bui.Call(bui.request_permission, bui.Permission.STORAGE)
249            )
250            return
251
252        self._save_state()
253        bui.containerwidget(edit=self._root_widget, transition='out_left')
254        assert bui.app.classic is not None
255        bui.app.ui_v1.set_main_menu_window(
256            stb.SoundtrackBrowserWindow(
257                origin_widget=self._soundtrack_button
258            ).get_root_widget()
259        )
260
261    def _back(self) -> None:
262        # pylint: disable=cyclic-import
263        from bauiv1lib.settings import allsettings
264
265        self._save_state()
266        bui.containerwidget(
267            edit=self._root_widget, transition=self._transition_out
268        )
269        assert bui.app.classic is not None
270        bui.app.ui_v1.set_main_menu_window(
271            allsettings.AllSettingsWindow(
272                transition='in_left'
273            ).get_root_widget()
274        )
275
276    def _save_state(self) -> None:
277        try:
278            sel = self._root_widget.get_selected_child()
279            if sel == self._sound_volume_numedit.minusbutton:
280                sel_name = 'SoundMinus'
281            elif sel == self._sound_volume_numedit.plusbutton:
282                sel_name = 'SoundPlus'
283            elif sel == self._music_volume_numedit.minusbutton:
284                sel_name = 'MusicMinus'
285            elif sel == self._music_volume_numedit.plusbutton:
286                sel_name = 'MusicPlus'
287            elif sel == self._soundtrack_button:
288                sel_name = 'Soundtrack'
289            elif sel == self._back_button:
290                sel_name = 'Back'
291            elif sel == self._vr_head_relative_audio_button:
292                sel_name = 'VRHeadRelative'
293            else:
294                raise ValueError(f'unrecognized selection \'{sel}\'')
295            assert bui.app.classic is not None
296            bui.app.ui_v1.window_states[type(self)] = sel_name
297        except Exception:
298            logging.exception('Error saving state for %s.', self)
299
300    def _restore_state(self) -> None:
301        try:
302            assert bui.app.classic is not None
303            sel_name = bui.app.ui_v1.window_states.get(type(self))
304            sel: bui.Widget | None
305            if sel_name == 'SoundMinus':
306                sel = self._sound_volume_numedit.minusbutton
307            elif sel_name == 'SoundPlus':
308                sel = self._sound_volume_numedit.plusbutton
309            elif sel_name == 'MusicMinus':
310                sel = self._music_volume_numedit.minusbutton
311            elif sel_name == 'MusicPlus':
312                sel = self._music_volume_numedit.plusbutton
313            elif sel_name == 'VRHeadRelative':
314                sel = self._vr_head_relative_audio_button
315            elif sel_name == 'Soundtrack':
316                sel = self._soundtrack_button
317            elif sel_name == 'Back':
318                sel = self._back_button
319            else:
320                sel = self._back_button
321            if sel:
322                bui.containerwidget(edit=self._root_widget, selected_child=sel)
323        except Exception:
324            logging.exception('Error restoring state for %s.', self)

Window for editing audio settings.

AudioSettingsWindow( transition: str = 'in_right', origin_widget: _bauiv1.Widget | None = None)
 20    def __init__(
 21        self,
 22        transition: str = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27        # pylint: disable=cyclic-import
 28        from bauiv1lib.popup import PopupMenu
 29        from bauiv1lib.config import ConfigNumberEdit
 30
 31        assert bui.app.classic is not None
 32        music = bui.app.classic.music
 33
 34        # If they provided an origin-widget, scale up from that.
 35        scale_origin: tuple[float, float] | None
 36        if origin_widget is not None:
 37            self._transition_out = 'out_scale'
 38            scale_origin = origin_widget.get_screen_space_center()
 39            transition = 'in_scale'
 40        else:
 41            self._transition_out = 'out_right'
 42            scale_origin = None
 43
 44        self._r = 'audioSettingsWindow'
 45
 46        spacing = 50.0
 47        width = 460.0
 48        height = 210.0
 49
 50        # Update: hard-coding head-relative audio to true now,
 51        # so not showing options.
 52        # show_vr_head_relative_audio = True if bui.app.vr_mode else False
 53        show_vr_head_relative_audio = False
 54
 55        if show_vr_head_relative_audio:
 56            height += 70
 57
 58        show_soundtracks = False
 59        if music.have_music_player():
 60            show_soundtracks = True
 61            height += spacing * 2.0
 62
 63        uiscale = bui.app.ui_v1.uiscale
 64        base_scale = (
 65            2.05
 66            if uiscale is bui.UIScale.SMALL
 67            else 1.6
 68            if uiscale is bui.UIScale.MEDIUM
 69            else 1.0
 70        )
 71        popup_menu_scale = base_scale * 1.2
 72
 73        super().__init__(
 74            root_widget=bui.containerwidget(
 75                size=(width, height),
 76                transition=transition,
 77                scale=base_scale,
 78                scale_origin_stack_offset=scale_origin,
 79                stack_offset=(0, -20)
 80                if uiscale is bui.UIScale.SMALL
 81                else (0, 0),
 82            )
 83        )
 84
 85        self._back_button = back_button = btn = bui.buttonwidget(
 86            parent=self._root_widget,
 87            position=(35, height - 55),
 88            size=(120, 60),
 89            scale=0.8,
 90            text_scale=1.2,
 91            label=bui.Lstr(resource='backText'),
 92            button_type='back',
 93            on_activate_call=self._back,
 94            autoselect=True,
 95        )
 96        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 97        v = height - 60
 98        v -= spacing * 1.0
 99        bui.textwidget(
100            parent=self._root_widget,
101            position=(width * 0.5, height - 32),
102            size=(0, 0),
103            text=bui.Lstr(resource=self._r + '.titleText'),
104            color=bui.app.ui_v1.title_color,
105            maxwidth=180,
106            h_align='center',
107            v_align='center',
108        )
109
110        bui.buttonwidget(
111            edit=self._back_button,
112            button_type='backSmall',
113            size=(60, 60),
114            label=bui.charstr(bui.SpecialChar.BACK),
115        )
116
117        self._sound_volume_numedit = svne = ConfigNumberEdit(
118            parent=self._root_widget,
119            position=(40, v),
120            xoffset=10,
121            configkey='Sound Volume',
122            displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
123            minval=0.0,
124            maxval=1.0,
125            increment=0.1,
126        )
127        if bui.app.ui_v1.use_toolbars:
128            bui.widget(
129                edit=svne.plusbutton,
130                right_widget=bui.get_special_widget('party_button'),
131            )
132        v -= spacing
133        self._music_volume_numedit = ConfigNumberEdit(
134            parent=self._root_widget,
135            position=(40, v),
136            xoffset=10,
137            configkey='Music Volume',
138            displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
139            minval=0.0,
140            maxval=1.0,
141            increment=0.1,
142            callback=music.music_volume_changed,
143            changesound=False,
144        )
145
146        v -= 0.5 * spacing
147
148        self._vr_head_relative_audio_button: bui.Widget | None
149        if show_vr_head_relative_audio:
150            v -= 40
151            bui.textwidget(
152                parent=self._root_widget,
153                position=(40, v + 24),
154                size=(0, 0),
155                text=bui.Lstr(resource=self._r + '.headRelativeVRAudioText'),
156                color=(0.8, 0.8, 0.8),
157                maxwidth=230,
158                h_align='left',
159                v_align='center',
160            )
161
162            popup = PopupMenu(
163                parent=self._root_widget,
164                position=(290, v),
165                width=120,
166                button_size=(135, 50),
167                scale=popup_menu_scale,
168                choices=['Auto', 'On', 'Off'],
169                choices_display=[
170                    bui.Lstr(resource='autoText'),
171                    bui.Lstr(resource='onText'),
172                    bui.Lstr(resource='offText'),
173                ],
174                current_choice=bui.app.config.resolve('VR Head Relative Audio'),
175                on_value_change_call=self._set_vr_head_relative_audio,
176            )
177            self._vr_head_relative_audio_button = popup.get_button()
178            bui.textwidget(
179                parent=self._root_widget,
180                position=(width * 0.5, v - 11),
181                size=(0, 0),
182                text=bui.Lstr(
183                    resource=self._r + '.headRelativeVRAudioInfoText'
184                ),
185                scale=0.5,
186                color=(0.7, 0.8, 0.7),
187                maxwidth=400,
188                flatness=1.0,
189                h_align='center',
190                v_align='center',
191            )
192            v -= 30
193        else:
194            self._vr_head_relative_audio_button = None
195
196        self._soundtrack_button: bui.Widget | None
197        if show_soundtracks:
198            v -= 1.2 * spacing
199            self._soundtrack_button = bui.buttonwidget(
200                parent=self._root_widget,
201                position=((width - 310) / 2, v),
202                size=(310, 50),
203                autoselect=True,
204                label=bui.Lstr(resource=self._r + '.soundtrackButtonText'),
205                on_activate_call=self._do_soundtracks,
206            )
207            v -= spacing * 0.5
208            bui.textwidget(
209                parent=self._root_widget,
210                position=(0, v),
211                size=(width, 20),
212                text=bui.Lstr(resource=self._r + '.soundtrackDescriptionText'),
213                flatness=1.0,
214                h_align='center',
215                scale=0.5,
216                color=(0.7, 0.8, 0.7, 1.0),
217                maxwidth=400,
218            )
219        else:
220            self._soundtrack_button = None
221
222        # Tweak a few navigation bits.
223        try:
224            bui.widget(edit=back_button, down_widget=svne.minusbutton)
225        except Exception:
226            logging.exception('Error wiring AudioSettingsWindow.')
227
228        self._restore_state()
Inherited Members
bauiv1._uitypes.Window
get_root_widget