// This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>. // // TotalRecall is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 3 only. // // TotalRecall is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with TotalRecall. If not, see <http://www.gnu.org/licenses/>. package info; import java.awt.Event; import java.awt.Toolkit; import java.awt.event.KeyEvent; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import javax.swing.JOptionPane; import control.Start; /** * Collects system-specific information. * * Values are determined only once, and then stored. * * @author Yuvi Masory */ public class SysInfo { public static final SysInfo sys = new SysInfo(); public final boolean isMacAny; public final boolean isMacOSX; public final boolean isLinux; public final boolean isGNOME; public final boolean isKDE; public final boolean isOpenJDK; public final boolean isWindowsAny; public final boolean isWindows7; public final boolean isSolaris; public final boolean isJava5; public final boolean isJava6; public final int menuKey; public final int chunkSizeInSeconds; public final int maxInterpolatedPixels; public final int jsInternalBufferSize; public final int jsExternalBufferSize; public final double interplationToleratedErrorZoneInSec; public final boolean useMnemonics; public final boolean useAWTFileChoosers; public final boolean useSheets; public final boolean launchedWithJWS; public final boolean preferDefaultJSMixerLine; public final boolean useMetalLAF; public final boolean mouseMode; public final boolean forceListen; public final boolean bandpassFilter; public final boolean useAudioDataSmoothingForWaveform; public final boolean useWaveformImageDataSmoothing; public final boolean interpolateFrames; public final boolean nanoInterplation; public final boolean antiAliasWaveform; public final boolean pulseAudioSystem; public final boolean doubleDraw; public final String aboutMessage; public final String menuKeyString; public final String userHomeDir; public final String updateAddress; public final String preferencesString; private SysInfo() { //was the program launched with Java Web Start? String jwsVal = System.getProperty("deployment.version"); if(jwsVal == null) { launchedWithJWS = false; } else { launchedWithJWS = true; } String jreVersion = System.getProperty("java.runtime.version"); if(jreVersion == null) { isJava5 = false; isJava6 = false; } else { if(jreVersion.startsWith("1.5")) { isJava5 = true; isJava6 = false; } else if(jreVersion.startsWith("1.6")) { isJava6 = true; isJava5 = false; } else { System.err.println("I don't understand what version of Java you are running"); isJava5 = false; isJava6 = false; } } //determine current operating system String osName = System.getProperty("os.name").toLowerCase(); if(osName == null) { isSolaris = isMacOSX = isMacAny = isLinux = isWindowsAny = isWindows7 = isOpenJDK = false; } else { if(osName.contains("windows 7")) { isWindowsAny = true; isWindows7 = true; isSolaris = isLinux = isMacOSX = isMacAny = isOpenJDK = false; } else if(osName.contains("win")) { isWindowsAny = true; isSolaris = isWindows7 = isLinux = isMacOSX = isMacAny = isOpenJDK = false; } else if(osName.contains("linux")) { isLinux = true; isSolaris = isWindowsAny = isWindows7 = isMacOSX = isMacAny = false; String vmName = System.getProperty("java.vm.name"); if(vmName == null) { isOpenJDK = false; } else { isOpenJDK = vmName.toLowerCase().contains("openjdk"); } } else if(osName.contains("mac os x")) { isMacOSX = true; isMacAny = true; isSolaris = isWindowsAny = isWindows7 = isLinux = isOpenJDK = false; } else if(osName.contains("mac")) { isMacAny = true; isSolaris = isWindowsAny = isWindows7 = isMacOSX = isLinux = isOpenJDK = false; } else if(osName.contains("solaris")) { isSolaris = true; isOpenJDK = isMacOSX = isMacAny = isLinux = isWindows7 = isWindowsAny = false; } else { isSolaris = isMacAny = isWindowsAny = isWindows7 = isMacOSX = isLinux = isOpenJDK = false; System.err.println("cannot recognize your operating system"); } } if(isLinux && isJava5) { if(runningCompiz()) { System.err.println("Compiz detected, exiting."); JOptionPane.showMessageDialog( null, Constants.programName + " has detected you are running Compiz and Java 5, which are incompatible.\n" + "Please either upgrade to Java 6 or turn off Compiz.\n" + "In Ubuntu you can turn off Compiz through System -> Preferences -> Appearance -> Visual Effects -> None\n", GUIConstants.errorDialogTitle, JOptionPane.ERROR_MESSAGE); System.exit(1); } } if(isOpenJDK) { //workaround to possible openjdk bug in Graphics.drawImage() doubleDraw = true; } else { doubleDraw = false; } //detect GNOME/KDE in Linux if(isLinux) { String desktopVar = System.getenv("DESKTOP_SESSION").toLowerCase(); if(desktopVar == null) { isGNOME = false; isKDE = false; } else if(desktopVar.contains("gnome")) { isGNOME = true; isKDE = false; } else if(desktopVar.contains("kde")) { isKDE = true; isGNOME = false; } else { isKDE = false; isGNOME = false; } } else { isGNOME = false; isKDE = false; } //what is the user's home directory? String homeVal = System.getProperty("user.home"); if(homeVal == null) { String curDir = null; try { curDir = new File(".").getCanonicalPath(); } catch (IOException e) { e.printStackTrace(); } if(curDir == null) { userHomeDir = ""; } else { userHomeDir = curDir; } } else { userHomeDir = homeVal; } //what is the correct update file location? if(isMacOSX) { updateAddress = "http://memory.psych.upenn.edu/files/software/TotalRecall/version_files/mac_version.txt"; } else if(isLinux) { updateAddress = "http://memory.psych.upenn.edu/files/software/TotalRecall/version_files/linux_version.txt"; } else { updateAddress = "http://memory.psych.upenn.edu/files/software/TotalRecall/version_files/windows_version.txt"; } //generate string displayed for "About this Program" aboutMessage = Constants.programName + " v" + Constants.programVersion + "\n" + "Author: " + Constants.authorString + "\n" + "Maintainer: " + Constants.maintainerEmail + "\n\n" + "Released by:" + "\n" + Constants.orgName + "\n" + Constants.orgAffiliationName + "\n" + Constants.orgHomepage + "\n\n" + "License: " + Constants.license + "\n" + Constants.licenseSite; //modifier key for menu actions, and its name menuKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); switch(menuKey) { case(Event.CTRL_MASK): menuKeyString = "Control"; break; case(KeyEvent.META_MASK): menuKeyString = (isLinux ? "Meta" : "Command"); break; case(KeyEvent.ALT_MASK): menuKeyString = (isMacAny ? "Option" : "Alt"); break; case(KeyEvent.SHIFT_MASK): menuKeyString = "Shift"; break; default: menuKeyString = "MenuKey"; } //customize appearance if(isMacOSX) { useAWTFileChoosers = true; useSheets = false; useMetalLAF = false; preferencesString = "Preferences"; useMnemonics = false; } else if(isMacAny) { useAWTFileChoosers = false; useSheets = false; useMetalLAF = false; preferencesString = "Preferences"; useMnemonics = false; } else if(isWindowsAny) { useAWTFileChoosers = false; useSheets = false; useMetalLAF = false; preferencesString = "Options"; useMnemonics = true; } else if(isLinux) { useAWTFileChoosers = false; useSheets = false; preferencesString = "Preferences"; useMnemonics = true; if(isJava5) { useMetalLAF = true; } else { useMetalLAF = false; } // //the Swing imitation of ClearLooks LAF doesn't draw menu item borders correctly, so use Java LAF "Metal" instead // if(isLinux && usingClearlooks()) { // useMetalLAF = true; // } // else { // useMetalLAF = false; // } } else { useAWTFileChoosers = false; useSheets = false; useMetalLAF = false; preferencesString = "Preferences"; useMnemonics = false; } //check for JS mixers boolean pulseAudioDefined = false; try { Class.forName("org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine"); pulseAudioDefined = true; } catch (Throwable t) { } pulseAudioSystem = pulseAudioDefined; //audio settings if(isMacOSX) { preferDefaultJSMixerLine = true; jsInternalBufferSize = 1024 * 3; jsExternalBufferSize = 1024 * 3; interpolateFrames = true; maxInterpolatedPixels = 10; interplationToleratedErrorZoneInSec = 0.25; nanoInterplation = false; } else if(isLinux) { preferDefaultJSMixerLine = true; jsInternalBufferSize = -1; jsExternalBufferSize = 1024 * 3; interpolateFrames = true; maxInterpolatedPixels = 15; interplationToleratedErrorZoneInSec = 0.25; nanoInterplation = false; } //ideally an ordered collection of contingencies in order of preference else if(isWindowsAny){ //Windows settings will serve as defaults preferDefaultJSMixerLine = true; //very bizarre, but if you explicitly request a MixerSourceLine (same class as you get automatically), audio is horrible jsInternalBufferSize = 1024 * 3; jsExternalBufferSize = 1024 * 3; interpolateFrames = true; maxInterpolatedPixels = 30; interplationToleratedErrorZoneInSec = 0.25; nanoInterplation = true; } else { preferDefaultJSMixerLine = true; jsInternalBufferSize = -1; jsExternalBufferSize = 1024 * 3; interpolateFrames = true; maxInterpolatedPixels = Integer.MAX_VALUE; interplationToleratedErrorZoneInSec = 0.25; nanoInterplation = true; } //performance optimiziations chunkSizeInSeconds = (int)Math.ceil(Toolkit.getDefaultToolkit().getScreenSize().getWidth() / GUIConstants.zoomlessPixelsPerSecond); //annotation optimizations mouseMode = true; if(Start.developerMode()) { forceListen = false; } else { forceListen = false; } //pretty waveform bandpassFilter = true; //essential for making words discernable useAudioDataSmoothingForWaveform = true; //essential for thickening the waveform useWaveformImageDataSmoothing = true; //prettier but blockier antiAliasWaveform = false; //no preference for it } private boolean runningCompiz() { try { File ps = new File("/bin/ps"); ProcessBuilder pb = new ProcessBuilder(ps.getAbsolutePath(), "-A"); Process psProc = pb.start(); psProc.waitFor(); // read the output of ps BufferedReader br = new BufferedReader(new InputStreamReader(psProc.getInputStream())); boolean runningCompiz = false; String line = null; while((line=br.readLine()) != null) { line = line.toLowerCase(); if ((line.endsWith("compiz")) || (line.endsWith("compiz.real"))) { runningCompiz = true; break; } } return runningCompiz; } catch(Exception e) { e.printStackTrace(); return false; } } @SuppressWarnings("unused") private boolean usingClearlooks() { try { File gconf = new File("/usr/bin/gconftool-2"); if(gconf.exists() == false) { return false; } ProcessBuilder pb = new ProcessBuilder(gconf.getAbsolutePath(), "-g", "/desktop/gnome/interface/gtk_theme"); Process psProc = pb.start(); psProc.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader(psProc.getInputStream())); boolean clearlooks = false; String line = null; while((line=br.readLine()) != null) { if ((line.toLowerCase().contains("clearlooks"))) { clearlooks = true; break; } } return clearlooks; } catch(Exception e) { e.printStackTrace(); return false; } } }