View Javadoc
1   /*
2    * Copyright 2021-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.unix.openbsd;
6   
7   import java.util.ArrayList;
8   import java.util.HashMap;
9   import java.util.HashSet;
10  import java.util.List;
11  import java.util.Map;
12  import java.util.Map.Entry;
13  import java.util.Set;
14  import java.util.regex.Matcher;
15  import java.util.regex.Pattern;
16  
17  import oshi.annotation.concurrent.Immutable;
18  import oshi.hardware.SoundCard;
19  import oshi.hardware.common.AbstractSoundCard;
20  import oshi.util.ExecutingCommand;
21  
22  /**
23   * OpenBSD soundcard.
24   */
25  @Immutable
26  final class OpenBsdSoundCard extends AbstractSoundCard {
27  
28      private static final Pattern AUDIO_AT = Pattern.compile("audio\\d+ at (.+)");
29      private static final Pattern PCI_AT = Pattern
30              .compile("(.+) at pci\\d+ dev \\d+ function \\d+ \"(.*)\" (rev .+):.*");
31  
32      /**
33       * Constructor for OpenBsdSoundCard.
34       *
35       * @param kernelVersion The version
36       * @param name          The name
37       * @param codec         The codec
38       */
39      OpenBsdSoundCard(String kernelVersion, String name, String codec) {
40          super(kernelVersion, name, codec);
41      }
42  
43      /**
44       * <p>
45       * getSoundCards.
46       * </p>
47       *
48       * @return a {@link java.util.List} object.
49       */
50      public static List<SoundCard> getSoundCards() {
51          List<String> dmesg = ExecutingCommand.runNative("dmesg");
52          // Iterate dmesg once to collect location of audioN
53          Set<String> names = new HashSet<>();
54          for (String line : dmesg) {
55              Matcher m = AUDIO_AT.matcher(line);
56              if (m.matches()) {
57                  names.add(m.group(1));
58              }
59          }
60          // Iterate again and add cards when they match the name
61          Map<String, String> nameMap = new HashMap<>();
62          Map<String, String> codecMap = new HashMap<>();
63          Map<String, String> versionMap = new HashMap<>();
64          String key = "";
65          for (String line : dmesg) {
66              Matcher m = PCI_AT.matcher(line);
67              if (m.matches() && names.contains(m.group(1))) {
68                  key = m.group(1);
69                  nameMap.put(key, m.group(2));
70                  versionMap.put(key, m.group(3));
71              } else if (!key.isEmpty()) {
72                  // Codec is on the next line
73                  int idx = line.indexOf("codec");
74                  if (idx >= 0) {
75                      idx = line.indexOf(':');
76                      codecMap.put(key, line.substring(idx + 1).trim());
77                  }
78                  // clear key so we don't keep looking
79                  key = "";
80              }
81          }
82          List<SoundCard> soundCards = new ArrayList<>();
83          for (Entry<String, String> entry : nameMap.entrySet()) {
84              soundCards.add(new OpenBsdSoundCard(versionMap.get(entry.getKey()), entry.getValue(),
85                      codecMap.get(entry.getKey())));
86          }
87          return soundCards;
88      }
89  }