/**
 * OSHI (https://github.com/oshi/oshi)
 *
 * Copyright (c) 2010 - 2019 The OSHI Project Team:
 * https://github.com/oshi/oshi/graphs/contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package oshi.hardware.platform.linux;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import oshi.hardware.common.AbstractSoundCard;
import oshi.util.FileUtil;

/**
 * Sound card data obtained via /proc/asound directory
 *
 * @author BilalAM
 */

public class LinuxSoundCard extends AbstractSoundCard {

    private static final String SC_PATH = "/proc/asound/";
    private static final String CARD_FOLDER = "card";
    private static final String CARDS_FILE = "cards";
    private static final String ID_FILE = "id";

    private static final Logger LOG = LoggerFactory.getLogger(LinuxSoundCard.class);

    public LinuxSoundCard(String kernelVersion, String name, String codec) {
        super(kernelVersion, name, codec);
    }

    /**
     * Method to find all the card folders contained in the <b>asound</b> folder
     * denoting the cards currently contained in our machine.
     *
     * @return : A list of files starting with 'card'
     */
    private static List<File> getCardFolders() {
        File cardsDirectory = new File(SC_PATH);
        List<File> cardFolders = new ArrayList<>();
        File[] allContents = cardsDirectory.listFiles();
        if (allContents != null) {
            for (File card : allContents) {
                if (card.getName().startsWith(CARD_FOLDER) && card.isDirectory()) {
                    cardFolders.add(card);
                }
            }
        } else {
            LOG.warn("No Audio Cards Found");
        }
        return cardFolders;
    }

    /**
     * Reads the 'version' file in the asound folder that contains the complete
     * name of the ALSA driver. Reads all the lines of the file and retrieves
     * the first line.
     *
     * @return The complete name of the ALSA driver currently residing in our
     *         machine
     */
    private static String getSoundCardVersion() {
        String driverVersion = FileUtil.getStringFromFile(SC_PATH + "version");
        return driverVersion.isEmpty() ? "not available" : driverVersion;
    }

    /**
     * Retrieves the codec of the sound card contained in the <b>codec</b> file.
     * The name of the codec is always the first line of that file. <br>
     * <b>Working</b> <br>
     * This converts the codec file into key value pairs using the
     * {@link FileUtil} class and then returns the value of the <b>Codec</b>
     * key.
     *
     * @param cardDir
     *            The sound card directory
     * @return The name of the codec
     */
    private static String getCardCodec(File cardDir) {
        String cardCodec = "";
        File[] cardFiles = cardDir.listFiles();
        if (cardFiles != null) {
            for (File file : cardFiles) {
                if (file.getName().startsWith("codec")) {
                    cardCodec = FileUtil.getKeyValueMapFromFile(file.getPath(), ":").get("Codec");
                }
            }
        }
        return cardCodec;
    }

    /**
     * Retrieves the name of the sound card by :
     * <ol>
     * <li>Reading the <b>id</b> file and comparing each id with the card id
     * present in the <b>cards</b> file</li>
     * <li>If the id and the card name matches , then it assigns that name to
     * {@literal cardName}</li>
     * </ol>
     *
     * @param file
     *            The sound card File.
     * @return The name of the sound card.
     */
    private static String getCardName(File file) {
        String cardName = "Not Found..";
        Map<String, String> cardNamePairs = FileUtil.getKeyValueMapFromFile(SC_PATH + "/" + CARDS_FILE, ":");
        String cardId = FileUtil.getStringFromFile(file.getPath() + "/" + ID_FILE);
        for (Map.Entry<String, String> entry : cardNamePairs.entrySet()) {
            if (entry.getKey().contains(cardId)) {
                cardName = entry.getValue();
                return cardName;
            }
        }
        return cardName;
    }

    /**
     * public method used by
     * {@link oshi.hardware.common.AbstractHardwareAbstractionLayer} to access
     * the sound cards.
     *
     * @return List of {@link LinuxSoundCard} objects.
     */
    public static List<LinuxSoundCard> getSoundCards() {
        List<LinuxSoundCard> soundCards = new ArrayList<>();
        for (File cardFile : getCardFolders()) {
            soundCards.add(new LinuxSoundCard(getSoundCardVersion(), getCardName(cardFile), getCardCodec(cardFile)));
        }
        return soundCards;
    }
}

@@ -4072,24 +4072,75 @@
 %22codec%22)) %7B%0A
+                    if (!file.isDirectory()) %7B%0A    
             
@@ -4222,24 +4222,839 @@
 t(%22Codec%22);%0A
+                    %7D else %7B%0A                        //on various centos environments, this is a subdirectory%0A                        //each file is usually named something like%0A                        //codec#0-0%0A                        //example : ac97#0-0%0A                        File%5B%5D codecs = file.listFiles();%0A                        if (codecs != null) %7B%0A                            for (File codec : codecs) %7B%0A                                if (!codec.isDirectory()%0A                                        && codec.getName().contains(%22#%22)) %7B%0A                                    cardCodec = codec.getName().substring(0, codec.getName().indexOf(%22#%22));%0A                                    break;%0A                                %7D%0A                            %7D%0A                        %7D%0A                    %7D%0A
             

Fix for #860 for sound card codec detection on centos7 and possibly other fedora based linux flavors (#861)