1/*
2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.media.sound;
27
28import java.security.AccessController;
29import java.security.PrivilegedAction;
30import java.util.StringTokenizer;
31
32/**
33 * Audio configuration class for exposing attributes specific to the platform or system.
34 *
35 * @author Kara Kytle
36 * @author Florian Bomers
37 */
38final class Platform {
39
40    // native library we need to load
41    private static final String libNameMain     = "jsound";
42    private static final String libNameALSA     = "jsoundalsa";
43    private static final String libNameDSound   = "jsoundds";
44
45    // extra libs handling: bit flags for each different library
46    public static final int LIB_MAIN     = 1;
47    public static final int LIB_ALSA     = 2;
48    public static final int LIB_DSOUND   = 4;
49
50    // bit field of the constants above. Willbe set in loadLibraries
51    private static int loadedLibs = 0;
52
53    // features: the main native library jsound reports which feature is
54    // contained in which lib
55    public static final int FEATURE_MIDIIO       = 1;
56    public static final int FEATURE_PORTS        = 2;
57    public static final int FEATURE_DIRECT_AUDIO = 3;
58
59    // SYSTEM CHARACTERISTICS
60    // vary according to hardware architecture
61
62    // intel is little-endian.  sparc is big-endian.
63    private static boolean bigEndian;
64
65    static {
66        if(Printer.trace)Printer.trace(">> Platform.java: static");
67
68        loadLibraries();
69        readProperties();
70    }
71
72    /**
73     * Private constructor.
74     */
75    private Platform() {
76    }
77
78    /**
79     * Dummy method for forcing initialization.
80     */
81    static void initialize() {
82        if(Printer.trace)Printer.trace("Platform: initialize()");
83    }
84
85    /**
86     * Determine whether the system is big-endian.
87     */
88    static boolean isBigEndian() {
89        return bigEndian;
90    }
91
92    /**
93     * Load the native library or libraries.
94     */
95    private static void loadLibraries() {
96        if(Printer.trace)Printer.trace(">>Platform.loadLibraries");
97
98        // load the main library
99        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
100            System.loadLibrary(libNameMain);
101            return null;
102        });
103        // just for the heck of it...
104        loadedLibs |= LIB_MAIN;
105
106        // now try to load extra libs. They are defined at compile time in the Makefile
107        // with the define EXTRA_SOUND_JNI_LIBS
108        String extraLibs = nGetExtraLibraries();
109        // the string is the libraries, separated by white space
110        StringTokenizer st = new StringTokenizer(extraLibs);
111        while (st.hasMoreTokens()) {
112            final String lib = st.nextToken();
113            try {
114                AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
115                    System.loadLibrary(lib);
116                    return null;
117                });
118
119                if (lib.equals(libNameALSA)) {
120                    loadedLibs |= LIB_ALSA;
121                    if (Printer.debug) Printer.debug("Loaded ALSA lib successfully.");
122                } else if (lib.equals(libNameDSound)) {
123                    loadedLibs |= LIB_DSOUND;
124                    if (Printer.debug) Printer.debug("Loaded DirectSound lib successfully.");
125                } else {
126                    if (Printer.err) Printer.err("Loaded unknown lib '"+lib+"' successfully.");
127                }
128            } catch (Throwable t) {
129                if (Printer.err) Printer.err("Couldn't load library "+lib+": "+t.toString());
130            }
131        }
132    }
133
134    static boolean isMidiIOEnabled() {
135        return isFeatureLibLoaded(FEATURE_MIDIIO);
136    }
137
138    static boolean isPortsEnabled() {
139        return isFeatureLibLoaded(FEATURE_PORTS);
140    }
141
142    static boolean isDirectAudioEnabled() {
143        return isFeatureLibLoaded(FEATURE_DIRECT_AUDIO);
144    }
145
146    private static boolean isFeatureLibLoaded(int feature) {
147        if (Printer.debug) Printer.debug("Platform: Checking for feature "+feature+"...");
148        int requiredLib = nGetLibraryForFeature(feature);
149        boolean isLoaded = (requiredLib != 0) && ((loadedLibs & requiredLib) == requiredLib);
150        if (Printer.debug) Printer.debug("          ...needs library "+requiredLib+". Result is loaded="+isLoaded);
151        return isLoaded;
152    }
153
154    // the following native methods are implemented in Platform.c
155    private static native boolean nIsBigEndian();
156    private static native String nGetExtraLibraries();
157    private static native int nGetLibraryForFeature(int feature);
158
159    /**
160     * Read the required system properties.
161     */
162    private static void readProperties() {
163        // $$fb 2002-03-06: implement check for endianness in native. Facilitates porting !
164        bigEndian = nIsBigEndian();
165    }
166}
167