PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/info/SysInfo.java

https://github.com/memlab/Penn-TotalRecall
Java | 479 lines | 356 code | 81 blank | 42 comment | 77 complexity | 978e60fc19dd84f17e2e056a80d4f052 MD5 | raw file
Possible License(s): LGPL-3.0
  1. // This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>.
  2. //
  3. // TotalRecall is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, version 3 only.
  6. //
  7. // TotalRecall is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU General Public License
  13. // along with TotalRecall. If not, see <http://www.gnu.org/licenses/>.
  14. package info;
  15. import java.awt.Event;
  16. import java.awt.Toolkit;
  17. import java.awt.event.KeyEvent;
  18. import java.io.BufferedReader;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.io.InputStreamReader;
  22. import javax.swing.JOptionPane;
  23. import control.Start;
  24. /**
  25. * Collects system-specific information.
  26. *
  27. * Values are determined only once, and then stored.
  28. *
  29. * @author Yuvi Masory
  30. */
  31. public class SysInfo {
  32. public static final SysInfo sys = new SysInfo();
  33. public final boolean isMacAny;
  34. public final boolean isMacOSX;
  35. public final boolean isLinux;
  36. public final boolean isGNOME;
  37. public final boolean isKDE;
  38. public final boolean isOpenJDK;
  39. public final boolean isWindowsAny;
  40. public final boolean isWindows7;
  41. public final boolean isSolaris;
  42. public final boolean isJava5;
  43. public final boolean isJava6;
  44. public final int menuKey;
  45. public final int chunkSizeInSeconds;
  46. public final int maxInterpolatedPixels;
  47. public final int jsInternalBufferSize;
  48. public final int jsExternalBufferSize;
  49. public final double interplationToleratedErrorZoneInSec;
  50. public final boolean useMnemonics;
  51. public final boolean useAWTFileChoosers;
  52. public final boolean useSheets;
  53. public final boolean launchedWithJWS;
  54. public final boolean preferDefaultJSMixerLine;
  55. public final boolean useMetalLAF;
  56. public final boolean mouseMode;
  57. public final boolean forceListen;
  58. public final boolean bandpassFilter;
  59. public final boolean useAudioDataSmoothingForWaveform;
  60. public final boolean useWaveformImageDataSmoothing;
  61. public final boolean interpolateFrames;
  62. public final boolean nanoInterplation;
  63. public final boolean antiAliasWaveform;
  64. public final boolean pulseAudioSystem;
  65. public final boolean doubleDraw;
  66. public final String aboutMessage;
  67. public final String menuKeyString;
  68. public final String userHomeDir;
  69. public final String updateAddress;
  70. public final String preferencesString;
  71. private SysInfo() {
  72. //was the program launched with Java Web Start?
  73. String jwsVal = System.getProperty("deployment.version");
  74. if(jwsVal == null) {
  75. launchedWithJWS = false;
  76. }
  77. else {
  78. launchedWithJWS = true;
  79. }
  80. String jreVersion = System.getProperty("java.runtime.version");
  81. if(jreVersion == null) {
  82. isJava5 = false;
  83. isJava6 = false;
  84. }
  85. else {
  86. if(jreVersion.startsWith("1.5")) {
  87. isJava5 = true;
  88. isJava6 = false;
  89. }
  90. else if(jreVersion.startsWith("1.6")) {
  91. isJava6 = true;
  92. isJava5 = false;
  93. }
  94. else {
  95. System.err.println("I don't understand what version of Java you are running");
  96. isJava5 = false;
  97. isJava6 = false;
  98. }
  99. }
  100. //determine current operating system
  101. String osName = System.getProperty("os.name").toLowerCase();
  102. if(osName == null) {
  103. isSolaris = isMacOSX = isMacAny = isLinux = isWindowsAny = isWindows7 = isOpenJDK = false;
  104. }
  105. else {
  106. if(osName.contains("windows 7")) {
  107. isWindowsAny = true;
  108. isWindows7 = true;
  109. isSolaris = isLinux = isMacOSX = isMacAny = isOpenJDK = false;
  110. }
  111. else if(osName.contains("win")) {
  112. isWindowsAny = true;
  113. isSolaris = isWindows7 = isLinux = isMacOSX = isMacAny = isOpenJDK = false;
  114. }
  115. else if(osName.contains("linux")) {
  116. isLinux = true;
  117. isSolaris = isWindowsAny = isWindows7 = isMacOSX = isMacAny = false;
  118. String vmName = System.getProperty("java.vm.name");
  119. if(vmName == null) {
  120. isOpenJDK = false;
  121. }
  122. else {
  123. isOpenJDK = vmName.toLowerCase().contains("openjdk");
  124. }
  125. }
  126. else if(osName.contains("mac os x")) {
  127. isMacOSX = true;
  128. isMacAny = true;
  129. isSolaris = isWindowsAny = isWindows7 = isLinux = isOpenJDK = false;
  130. }
  131. else if(osName.contains("mac")) {
  132. isMacAny = true;
  133. isSolaris = isWindowsAny = isWindows7 = isMacOSX = isLinux = isOpenJDK = false;
  134. }
  135. else if(osName.contains("solaris")) {
  136. isSolaris = true;
  137. isOpenJDK = isMacOSX = isMacAny = isLinux = isWindows7 = isWindowsAny = false;
  138. }
  139. else {
  140. isSolaris = isMacAny = isWindowsAny = isWindows7 = isMacOSX = isLinux = isOpenJDK = false;
  141. System.err.println("cannot recognize your operating system");
  142. }
  143. }
  144. if(isLinux && isJava5) {
  145. if(runningCompiz()) {
  146. System.err.println("Compiz detected, exiting.");
  147. JOptionPane.showMessageDialog(
  148. null,
  149. Constants.programName + " has detected you are running Compiz and Java 5, which are incompatible.\n" +
  150. "Please either upgrade to Java 6 or turn off Compiz.\n" +
  151. "In Ubuntu you can turn off Compiz through System -> Preferences -> Appearance -> Visual Effects -> None\n",
  152. GUIConstants.errorDialogTitle,
  153. JOptionPane.ERROR_MESSAGE);
  154. System.exit(1);
  155. }
  156. }
  157. if(isOpenJDK) { //workaround to possible openjdk bug in Graphics.drawImage()
  158. doubleDraw = true;
  159. }
  160. else {
  161. doubleDraw = false;
  162. }
  163. //detect GNOME/KDE in Linux
  164. if(isLinux) {
  165. String desktopVar = System.getenv("DESKTOP_SESSION").toLowerCase();
  166. if(desktopVar == null) {
  167. isGNOME = false;
  168. isKDE = false;
  169. }
  170. else if(desktopVar.contains("gnome")) {
  171. isGNOME = true;
  172. isKDE = false;
  173. }
  174. else if(desktopVar.contains("kde")) {
  175. isKDE = true;
  176. isGNOME = false;
  177. }
  178. else {
  179. isKDE = false;
  180. isGNOME = false;
  181. }
  182. }
  183. else {
  184. isGNOME = false;
  185. isKDE = false;
  186. }
  187. //what is the user's home directory?
  188. String homeVal = System.getProperty("user.home");
  189. if(homeVal == null) {
  190. String curDir = null;
  191. try {
  192. curDir = new File(".").getCanonicalPath();
  193. }
  194. catch (IOException e) {
  195. e.printStackTrace();
  196. }
  197. if(curDir == null) {
  198. userHomeDir = "";
  199. }
  200. else {
  201. userHomeDir = curDir;
  202. }
  203. }
  204. else {
  205. userHomeDir = homeVal;
  206. }
  207. //what is the correct update file location?
  208. if(isMacOSX) {
  209. updateAddress = "http://memory.psych.upenn.edu/files/software/TotalRecall/version_files/mac_version.txt";
  210. }
  211. else if(isLinux) {
  212. updateAddress = "http://memory.psych.upenn.edu/files/software/TotalRecall/version_files/linux_version.txt";
  213. }
  214. else {
  215. updateAddress = "http://memory.psych.upenn.edu/files/software/TotalRecall/version_files/windows_version.txt";
  216. }
  217. //generate string displayed for "About this Program"
  218. aboutMessage =
  219. Constants.programName + " v" + Constants.programVersion + "\n" +
  220. "Author: " + Constants.authorString + "\n" +
  221. "Maintainer: " + Constants.maintainerEmail + "\n\n" +
  222. "Released by:" + "\n" +
  223. Constants.orgName + "\n" +
  224. Constants.orgAffiliationName + "\n" +
  225. Constants.orgHomepage + "\n\n" +
  226. "License: " + Constants.license + "\n" +
  227. Constants.licenseSite;
  228. //modifier key for menu actions, and its name
  229. menuKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
  230. switch(menuKey) {
  231. case(Event.CTRL_MASK): menuKeyString = "Control"; break;
  232. case(KeyEvent.META_MASK): menuKeyString = (isLinux ? "Meta" : "Command"); break;
  233. case(KeyEvent.ALT_MASK): menuKeyString = (isMacAny ? "Option" : "Alt"); break;
  234. case(KeyEvent.SHIFT_MASK): menuKeyString = "Shift"; break;
  235. default: menuKeyString = "MenuKey";
  236. }
  237. //customize appearance
  238. if(isMacOSX) {
  239. useAWTFileChoosers = true;
  240. useSheets = false;
  241. useMetalLAF = false;
  242. preferencesString = "Preferences";
  243. useMnemonics = false;
  244. }
  245. else if(isMacAny) {
  246. useAWTFileChoosers = false;
  247. useSheets = false;
  248. useMetalLAF = false;
  249. preferencesString = "Preferences";
  250. useMnemonics = false;
  251. }
  252. else if(isWindowsAny) {
  253. useAWTFileChoosers = false;
  254. useSheets = false;
  255. useMetalLAF = false;
  256. preferencesString = "Options";
  257. useMnemonics = true;
  258. }
  259. else if(isLinux) {
  260. useAWTFileChoosers = false;
  261. useSheets = false;
  262. preferencesString = "Preferences";
  263. useMnemonics = true;
  264. if(isJava5) {
  265. useMetalLAF = true;
  266. }
  267. else {
  268. useMetalLAF = false;
  269. }
  270. // //the Swing imitation of ClearLooks LAF doesn't draw menu item borders correctly, so use Java LAF "Metal" instead
  271. // if(isLinux && usingClearlooks()) {
  272. // useMetalLAF = true;
  273. // }
  274. // else {
  275. // useMetalLAF = false;
  276. // }
  277. }
  278. else {
  279. useAWTFileChoosers = false;
  280. useSheets = false;
  281. useMetalLAF = false;
  282. preferencesString = "Preferences";
  283. useMnemonics = false;
  284. }
  285. //check for JS mixers
  286. boolean pulseAudioDefined = false;
  287. try {
  288. Class.forName("org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine");
  289. pulseAudioDefined = true;
  290. }
  291. catch (Throwable t) {
  292. }
  293. pulseAudioSystem = pulseAudioDefined;
  294. //audio settings
  295. if(isMacOSX) {
  296. preferDefaultJSMixerLine = true;
  297. jsInternalBufferSize = 1024 * 3;
  298. jsExternalBufferSize = 1024 * 3;
  299. interpolateFrames = true;
  300. maxInterpolatedPixels = 10;
  301. interplationToleratedErrorZoneInSec = 0.25;
  302. nanoInterplation = false;
  303. }
  304. else if(isLinux) {
  305. preferDefaultJSMixerLine = true;
  306. jsInternalBufferSize = -1;
  307. jsExternalBufferSize = 1024 * 3;
  308. interpolateFrames = true;
  309. maxInterpolatedPixels = 15;
  310. interplationToleratedErrorZoneInSec = 0.25;
  311. nanoInterplation = false;
  312. }
  313. //ideally an ordered collection of contingencies in order of preference
  314. else if(isWindowsAny){ //Windows settings will serve as defaults
  315. preferDefaultJSMixerLine = true; //very bizarre, but if you explicitly request a MixerSourceLine (same class as you get automatically), audio is horrible
  316. jsInternalBufferSize = 1024 * 3;
  317. jsExternalBufferSize = 1024 * 3;
  318. interpolateFrames = true;
  319. maxInterpolatedPixels = 30;
  320. interplationToleratedErrorZoneInSec = 0.25;
  321. nanoInterplation = true;
  322. }
  323. else {
  324. preferDefaultJSMixerLine = true;
  325. jsInternalBufferSize = -1;
  326. jsExternalBufferSize = 1024 * 3;
  327. interpolateFrames = true;
  328. maxInterpolatedPixels = Integer.MAX_VALUE;
  329. interplationToleratedErrorZoneInSec = 0.25;
  330. nanoInterplation = true;
  331. }
  332. //performance optimiziations
  333. chunkSizeInSeconds = (int)Math.ceil(Toolkit.getDefaultToolkit().getScreenSize().getWidth() / GUIConstants.zoomlessPixelsPerSecond);
  334. //annotation optimizations
  335. mouseMode = true;
  336. if(Start.developerMode()) {
  337. forceListen = false;
  338. }
  339. else {
  340. forceListen = false;
  341. }
  342. //pretty waveform
  343. bandpassFilter = true; //essential for making words discernable
  344. useAudioDataSmoothingForWaveform = true; //essential for thickening the waveform
  345. useWaveformImageDataSmoothing = true; //prettier but blockier
  346. antiAliasWaveform = false; //no preference for it
  347. }
  348. private boolean runningCompiz() {
  349. try {
  350. File ps = new File("/bin/ps");
  351. ProcessBuilder pb = new ProcessBuilder(ps.getAbsolutePath(), "-A");
  352. Process psProc = pb.start();
  353. psProc.waitFor();
  354. // read the output of ps
  355. BufferedReader br = new BufferedReader(new InputStreamReader(psProc.getInputStream()));
  356. boolean runningCompiz = false;
  357. String line = null;
  358. while((line=br.readLine()) != null) {
  359. line = line.toLowerCase();
  360. if ((line.endsWith("compiz")) || (line.endsWith("compiz.real"))) {
  361. runningCompiz = true;
  362. break;
  363. }
  364. }
  365. return runningCompiz;
  366. }
  367. catch(Exception e) {
  368. e.printStackTrace();
  369. return false;
  370. }
  371. }
  372. @SuppressWarnings("unused")
  373. private boolean usingClearlooks() {
  374. try {
  375. File gconf = new File("/usr/bin/gconftool-2");
  376. if(gconf.exists() == false) {
  377. return false;
  378. }
  379. ProcessBuilder pb = new ProcessBuilder(gconf.getAbsolutePath(), "-g", "/desktop/gnome/interface/gtk_theme");
  380. Process psProc = pb.start();
  381. psProc.waitFor();
  382. BufferedReader br = new BufferedReader(new InputStreamReader(psProc.getInputStream()));
  383. boolean clearlooks = false;
  384. String line = null;
  385. while((line=br.readLine()) != null) {
  386. if ((line.toLowerCase().contains("clearlooks"))) {
  387. clearlooks = true;
  388. break;
  389. }
  390. }
  391. return clearlooks;
  392. }
  393. catch(Exception e) {
  394. e.printStackTrace();
  395. return false;
  396. }
  397. }
  398. }