<commit_before>﻿// Copyright (c) 2007-2017 ppy Pty Ltd <<EMAIL>>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE

using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Graphics;
using System.Collections.Generic;
using System.Linq;

namespace osu.Game.Overlays.Options.Sections.Audio
{
    public class AudioDevicesOptions : OptionsSubsection
    {
        protected override string Header => "Devices";

        private AudioManager audio;
        private OptionDropdown<string> dropdown;

        [BackgroundDependencyLoader]
        private void load(AudioManager audio)
        {
            this.audio = audio;
        }

        protected override void Dispose(bool isDisposing)
        {
            base.Dispose(isDisposing);

            audio.OnNewDevice -= onDeviceChanged;
            audio.OnLostDevice -= onDeviceChanged;
        }

        private void updateItems()
        {
            var deviceItems = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("Default", string.Empty) };
            deviceItems.AddRange(audio.AudioDeviceNames.Select(d => new KeyValuePair<string, string>(d, d)));

            var preferredDeviceName = audio.AudioDevice.Value;
            if (deviceItems.All(kv => kv.Value != preferredDeviceName))
                deviceItems.Add(new KeyValuePair<string, string>(preferredDeviceName, preferredDeviceName));

            dropdown.Items = deviceItems;
        }

        private void onDeviceChanged(string name) => updateItems();

        protected override void LoadComplete()
        {
            base.LoadComplete();

            Children = new Drawable[]
            {
                dropdown = new OptionDropdown<string>
                {
                    Bindable = audio.AudioDevice
                },
            };
<commit_msg>Fix crash caused by multiple identical audio device names<commit_after>﻿// Copyright (c) 2007-2017 ppy Pty Ltd <<EMAIL>>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE

using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Graphics;
using System.Collections.Generic;
using System.Linq;

namespace osu.Game.Overlays.Options.Sections.Audio
{
    public class AudioDevicesOptions : OptionsSubsection
    {
        protected override string Header => "Devices";

        private AudioManager audio;
        private OptionDropdown<string> dropdown;

        [BackgroundDependencyLoader]
        private void load(AudioManager audio)
        {
            this.audio = audio;
        }

        protected override void Dispose(bool isDisposing)
        {
            base.Dispose(isDisposing);

            audio.OnNewDevice -= onDeviceChanged;
            audio.OnLostDevice -= onDeviceChanged;
        }

        private void updateItems()
        {
            var deviceItems = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("Default", string.Empty) };
            deviceItems.AddRange(audio.AudioDeviceNames.Select(d => new KeyValuePair<string, string>(d, d)));

            var preferredDeviceName = audio.AudioDevice.Value;
            if (deviceItems.All(kv => kv.Value != preferredDeviceName))
                deviceItems.Add(new KeyValuePair<string, string>(preferredDeviceName, preferredDeviceName));

            // The option dropdown for audio device selection lists all audio
            // device names. Dropdowns, however, may not have multiple identical
            // keys. Thus, we remove duplicate audio device names from
            // the dropdown. BASS does not give us a simple mechanism to select
            // specific audio devices in such a case anyways.This functionality would
            // require OS-specific and involved code.
            dropdown.Items = deviceItems.Distinct().ToList();
        }

        private void onDeviceChanged(string name) => updateItems();

        protected override void LoadComplete()
        {
            base.LoadComplete();

            Children = new Drawable[]
            {
                dropdown = new OptionDropdown<string>
                {
                    Bindable = audio.AudioDevice
                },
            };

{'fraction_non_alphanumeric': 0.08812529219261338, 'fraction_numerical': 0.0037400654511453952, 'mean_word_length': 2.271406727828746, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7589098', 'n_tokens_mistral': 1093, 'n_tokens_neox': 1040, 'n_words': 275}