/src/org/mt4j/input/InputManager.java

http://mt4j.googlecode.com/ · Java · 391 lines · 199 code · 50 blank · 142 comment · 22 complexity · 63307f5c176f7ad32c1fbe2a7905aedc MD5 · raw file

  1. /***********************************************************************
  2. * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. ***********************************************************************/
  18. package org.mt4j.input;
  19. import java.awt.Cursor;
  20. import java.awt.Image;
  21. import java.awt.Point;
  22. import java.awt.Toolkit;
  23. import java.awt.image.MemoryImageSource;
  24. import java.io.FileInputStream;
  25. import java.io.IOException;
  26. import java.io.InputStream;
  27. import java.util.ArrayList;
  28. import java.util.Arrays;
  29. import java.util.Collection;
  30. import java.util.HashMap;
  31. import java.util.List;
  32. import java.util.Map;
  33. import java.util.Properties;
  34. import java.util.Set;
  35. import org.mt4j.MTApplication;
  36. import org.mt4j.input.inputProcessors.globalProcessors.AbstractGlobalInputProcessor;
  37. import org.mt4j.input.inputSources.AbstractInputSource;
  38. import org.mt4j.input.inputSources.IinputSourceListener;
  39. import org.mt4j.input.inputSources.KeyboardInputSource;
  40. import org.mt4j.input.inputSources.MouseInputSource;
  41. import org.mt4j.input.inputSources.MultipleMiceInputSource;
  42. import org.mt4j.input.inputSources.TuioInputSource;
  43. import org.mt4j.input.inputSources.Win7NativeTouchSource;
  44. import org.mt4j.sceneManagement.Iscene;
  45. import org.mt4j.util.MT4jSettings;
  46. import org.mt4j.util.logging.ILogger;
  47. import org.mt4j.util.logging.MTLoggerFactory;
  48. /**
  49. * Manages the InputSources and Inputprocessors for each scene.
  50. * Starts up the default input sources.
  51. *
  52. * @author Christopher Ruff
  53. */
  54. public class InputManager {
  55. /** The Constant logger. */
  56. private static final ILogger logger = MTLoggerFactory.getLogger(InputManager.class.getName());
  57. static{
  58. // logger.setLevel(ILogger.ERROR);
  59. // logger.setLevel(ILogger.DEBUG);
  60. logger.setLevel(ILogger.INFO);
  61. }
  62. /** The registered input sources. */
  63. private List<AbstractInputSource> registeredInputSources;
  64. /** The In processor to scene. */
  65. private Map<AbstractGlobalInputProcessor, Iscene> inputProcessorsToScene;
  66. /** The pa. */
  67. private MTApplication app;
  68. /**
  69. * Instantiates a new input manager.
  70. *
  71. * @param pa the processing context
  72. */
  73. public InputManager(MTApplication pa) {
  74. this(pa, true);
  75. }
  76. /**
  77. * Instantiates a new input manager.
  78. *
  79. * @param pa the processing context
  80. */
  81. public InputManager(MTApplication pa, boolean registerDefaultSources) {
  82. super();
  83. this.registeredInputSources = new ArrayList<AbstractInputSource>();
  84. this.inputProcessorsToScene = new HashMap<AbstractGlobalInputProcessor, Iscene>();
  85. this.app = pa;
  86. if (registerDefaultSources)
  87. this.registerDefaultInputSources();
  88. }
  89. /**
  90. * Initialize default input sources.
  91. */
  92. protected void registerDefaultInputSources(){
  93. boolean enableMultiMouse = false;
  94. Properties properties = new Properties();
  95. try {
  96. FileInputStream fi = new FileInputStream(MT4jSettings.getInstance().getDefaultSettingsPath() + "Settings.txt");
  97. properties.load(fi);
  98. enableMultiMouse = Boolean.parseBoolean(properties.getProperty("MultiMiceEnabled", "false").trim());
  99. }catch (Exception e) {
  100. logger.debug("Failed to load Settings.txt from the File system. Trying to load it from classpath..");
  101. try {
  102. InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("Settings.txt");
  103. if (in != null){
  104. properties.load(in);
  105. enableMultiMouse = Boolean.parseBoolean(properties.getProperty("MultiMiceEnabled", "false").trim());
  106. }else{
  107. logger.debug("Couldnt load Settings.txt as a resource. Using defaults.");
  108. }
  109. } catch (IOException e1) {
  110. logger.error("Couldnt load Settings.txt. Using defaults.");
  111. e1.printStackTrace();
  112. }
  113. }
  114. if (enableMultiMouse){
  115. try {
  116. //Register single or multiple mice input source
  117. int connectedMice = MultipleMiceInputSource.getConnectedMouseCount();
  118. // /*
  119. logger.info("Found mice: " + connectedMice);
  120. if (connectedMice >= 2){ //FIXME should be > 1, but manymouse often detects more that arent there!?
  121. logger.info("-> Multiple Mice detected!");
  122. MultipleMiceInputSource multipleMice = new MultipleMiceInputSource(app);
  123. multipleMice.setMTApp(app);
  124. this.registerInputSource(multipleMice);
  125. this.hideCursorInFrame();
  126. }else{
  127. // */
  128. MouseInputSource mouseInput = new MouseInputSource(app);
  129. this.registerInputSource(mouseInput);
  130. }
  131. // */
  132. } catch (Exception e) {
  133. e.printStackTrace();
  134. //Use default mouse input source
  135. MouseInputSource mouseInput = new MouseInputSource(app);
  136. this.registerInputSource(mouseInput);
  137. }
  138. }
  139. else{
  140. // */
  141. MouseInputSource mouseInput = new MouseInputSource(app);
  142. this.registerInputSource(mouseInput);
  143. }
  144. // */
  145. //Check if we run windows 7
  146. if (System.getProperty("os.name").toLowerCase().contains("windows 7")){
  147. Win7NativeTouchSource win7NativeInput = new Win7NativeTouchSource(app);
  148. if (win7NativeInput.isSuccessfullySetup()){
  149. this.registerInputSource(win7NativeInput);
  150. }
  151. }
  152. //check which versions it supports and only start there!
  153. /*
  154. if (System.getProperty("os.name").toLowerCase().contains("mac os x")){
  155. this.registerInputSource(new MacTrackpadSource(app));
  156. }
  157. */
  158. KeyboardInputSource keyInput= new KeyboardInputSource(app);
  159. TuioInputSource tuioInput = new TuioInputSource(app);
  160. // MuitoInputSource muitoInput = new MuitoInputSource(pa, "localhost", 6666);
  161. this.registerInputSource(keyInput);
  162. this.registerInputSource(tuioInput);
  163. }
  164. /**
  165. * Registers a new input source for the application.
  166. *
  167. * @param newInputSource the new input source
  168. */
  169. public void registerInputSource(AbstractInputSource newInputSource){
  170. if (!registeredInputSources.contains(newInputSource)){
  171. registeredInputSources.add(newInputSource);
  172. //Add all processors to the new input source
  173. Set<AbstractGlobalInputProcessor> set = inputProcessorsToScene.keySet();
  174. for (AbstractGlobalInputProcessor processor : set) {
  175. //newInputSource.addInputListener(processor);
  176. this.saveAddInputListenerToSource(newInputSource, processor);
  177. }
  178. //Inform the input source that it is now registered with the application
  179. newInputSource.onRegistered();
  180. }else{
  181. logger.error("input source already registered! - " + newInputSource);
  182. }
  183. }
  184. /**
  185. * Unregisters a input source.
  186. * @param is the input source
  187. */
  188. public void unregisterInputSource(AbstractInputSource is){
  189. synchronized (registeredInputSources) {
  190. if (registeredInputSources.contains(is)){
  191. registeredInputSources.remove(is);
  192. //Inform the input source that it is now UN-registered from the application
  193. is.onUnregistered();
  194. }
  195. }
  196. }
  197. /**
  198. * Gets the input sources.
  199. * @return the input sources
  200. */
  201. public AbstractInputSource[] getInputSources(){
  202. return this.registeredInputSources.toArray(new AbstractInputSource[this.registeredInputSources.size()]);
  203. }
  204. /**
  205. * Gets the registered input sources.
  206. *
  207. * @return the registered input sources
  208. * @deprecated use getInputSources() instead
  209. */
  210. public Collection<AbstractInputSource> getRegisteredInputSources(){
  211. return this.registeredInputSources;
  212. }
  213. /**
  214. * Hides the mousecursor in multiple mice mode.
  215. */
  216. private void hideCursorInFrame(){
  217. int[] pixels = new int[16 * 16];
  218. Image image = Toolkit.getDefaultToolkit().createImage(
  219. new MemoryImageSource(16, 16, pixels, 0, 16));
  220. Cursor transparentCursor =
  221. Toolkit.getDefaultToolkit().createCustomCursor
  222. (image, new Point(0, 0), "invisibleCursor");
  223. app.frame.setCursor(transparentCursor);
  224. }
  225. /**
  226. * Registers a new inputprocessor and adds it to the inputsources as listeners.
  227. *
  228. * @param scene the scene
  229. * @param inputprocessor the input processor
  230. */
  231. public void registerGlobalInputProcessor(Iscene scene, AbstractGlobalInputProcessor inputprocessor){
  232. //By default disable the registered global input processor, so it doesent accidently
  233. //send events to a not even visible scene
  234. //-Only enable it if the scene is the currently active scene
  235. //-If a scene becomes active the processors will also be enabled
  236. // if (app.getCurrentScene() != null && app.getCurrentScene().equals(scene)){
  237. if (scene.equals(app.getCurrentScene())){
  238. inputprocessor.setDisabled(false);
  239. }else{
  240. inputprocessor.setDisabled(true);
  241. }
  242. inputProcessorsToScene.put(inputprocessor, scene);
  243. //Register the processor with all registered inputsources
  244. for (AbstractInputSource source: registeredInputSources){
  245. this.saveAddInputListenerToSource(source, inputprocessor);
  246. }
  247. }
  248. private void saveAddInputListenerToSource(AbstractInputSource source, AbstractGlobalInputProcessor inputprocessor){
  249. //Only add input processor to input sources
  250. //that fire the event type that the processor is interested in
  251. // if (source.firesEventType(inputprocessor.getListenEventType())){
  252. List<IinputSourceListener> sourceListener = Arrays.asList(source.getInputListeners());
  253. if (!sourceListener.contains(inputprocessor)){ //Prevent adding same global input processor twice
  254. source.addInputListener(inputprocessor);
  255. }
  256. // }
  257. }
  258. /**
  259. * Unregisters a inputprocessor from _all_ the registered inputsources.
  260. *
  261. * @param inputprocessor the input processor
  262. */
  263. public void unregisterGlobalInputProcessor(AbstractGlobalInputProcessor inputprocessor){
  264. /*
  265. Set set = InprocessorToScene.keySet();
  266. for (Iterator iter = set.iterator(); iter.hasNext();) {
  267. AbstractInputprocessor processor = (AbstractInputprocessor) iter.next();
  268. //Check if the processor is registered here with a scene
  269. if (processor.equals(inputprocessor)){
  270. if (InprocessorToScene.get(processor).equals(scene)){
  271. for (AbstractInputSource source: registeredInputSources){
  272. source.removeInputListener(inputprocessor);
  273. }
  274. }
  275. }
  276. }
  277. */
  278. //Remove the input processor from the processor->scene map
  279. if (inputProcessorsToScene.containsKey(inputprocessor)){
  280. inputProcessorsToScene.remove(inputprocessor);
  281. }
  282. for (AbstractInputSource source: registeredInputSources){
  283. source.removeInputListener(inputprocessor);
  284. }
  285. }
  286. /**
  287. * Gets the global inputprocessors associated with the specified scene.
  288. *
  289. * @param scene the scene
  290. *
  291. * @return the scene inputprocessors
  292. */
  293. public AbstractGlobalInputProcessor[] getGlobalInputProcessors(Iscene scene){
  294. List<AbstractGlobalInputProcessor> processors = new ArrayList<AbstractGlobalInputProcessor>();
  295. Set<AbstractGlobalInputProcessor> set = inputProcessorsToScene.keySet();
  296. for (AbstractGlobalInputProcessor processor : set) {
  297. if (inputProcessorsToScene.get(processor).equals(scene)) {
  298. processors.add(processor);
  299. }
  300. }
  301. return processors.toArray(new AbstractGlobalInputProcessor[processors.size()]);
  302. }
  303. /**
  304. * Enables the global inputprocessors that are associated with the given scene.
  305. *
  306. * @param scene the scene
  307. */
  308. public void enableGlobalInputProcessors(Iscene scene){
  309. Set<AbstractGlobalInputProcessor> set = inputProcessorsToScene.keySet();
  310. for (AbstractGlobalInputProcessor processor : set) {
  311. if (inputProcessorsToScene.get(processor).equals(scene)) {
  312. processor.setDisabled(false);
  313. }
  314. }
  315. }
  316. /**
  317. * Disables the global inputprocessors that are associated with the given scene.
  318. *
  319. * @param scene the scene
  320. */
  321. public void disableGlobalInputProcessors(Iscene scene){
  322. Set<AbstractGlobalInputProcessor> set = inputProcessorsToScene.keySet();
  323. for (AbstractGlobalInputProcessor processor : set) {
  324. if (inputProcessorsToScene.get(processor).equals(scene)) {
  325. processor.setDisabled(true);
  326. }
  327. }
  328. }
  329. /**
  330. * Removes input processors of the specified scene from listening to the registered input sources.
  331. *
  332. * @param scene the scene
  333. */
  334. public void removeGlobalInputProcessors(Iscene scene){
  335. AbstractGlobalInputProcessor[] sceneProcessors = this.getGlobalInputProcessors(scene);
  336. for (AbstractGlobalInputProcessor abstractGlobalInputProcessor : sceneProcessors) {
  337. this.unregisterGlobalInputProcessor(abstractGlobalInputProcessor);
  338. }
  339. }
  340. }