2 * Copyright 2008 ZXing authors
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
17 package com.google.zxing.client.rim;
\r
19 import com.google.zxing.client.rim.util.Log;
\r
20 import net.rim.blackberry.api.invoke.CameraArguments;
\r
21 import net.rim.blackberry.api.invoke.Invoke;
\r
22 import net.rim.device.api.system.Characters;
\r
23 import net.rim.device.api.system.EventInjector;
\r
24 import net.rim.device.api.ui.UiApplication;
\r
27 * Singleton used to control access to the camera.
\r
28 * Unfortunatly, the Camera API only allows invoking the camera.
\r
30 * Note: This code still contains experimental code to determine and set the camera resolution by
\r
31 * using system level key events, but didn't not function reliably and is not used.
\r
33 * This code was contributed by LifeMarks.
\r
35 * @author Matt York (matt@lifemarks.mobi)
\r
37 final class Camera {
\r
39 /** milliseconds to wait before starting key strokes */
\r
40 private static final int INITIALIZATION_TIME_MS = 500; // simulator seems to need >= 500
\r
41 private static final int KEY_PAUSE_TIME_MS = 100; // simulator seems to need >= 100
\r
43 private static Camera instance;
\r
45 /** Attempting to set camera resolution is disabled. */
\r
46 private final boolean setResolution = false;
\r
52 * Returns the single instance of the camera.
\r
54 static Camera getInstance() {
\r
55 if (instance == null) {
\r
56 instance = new Camera();
\r
62 * Starts the blackberry camera application.
\r
65 Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments());
\r
66 if (setResolution) {
\r
67 sleep(INITIALIZATION_TIME_MS);
\r
73 * Exits the blackberry camera application.
\r
76 if (setResolution) {
\r
77 setMaxResolution(); // for now, we dont know the original resolution setting. Assume it was max res.
\r
78 sleep(KEY_PAUSE_TIME_MS);
\r
80 sleep(3000); // this sleep is needed for the esc to be processed(3000 originally)
\r
81 UiApplication app = UiApplication.getUiApplication();
\r
83 Log.info("active app: " + app.getClass().getName());
\r
84 if (app.isForeground()) {
\r
85 Log.info("Lifemarks is the foreground app.");
\r
87 Log.info("Lifemarks is not the foreground app. Attempt to close camera.");
\r
88 keyUpAndDown(Characters.ESCAPE); // need two (no timeout in between esc key presses seems to work best)
\r
89 keyUpAndDown(Characters.ESCAPE);
\r
92 Log.error("??? app is null ???");
\r
97 * Sets the camera resolution to it's minimum.
\r
98 * Note: currently disabled.
\r
100 private static void setMaxResolution() {
\r
101 Log.info("Setting resolution to max.");
\r
102 accessResolutionMenuAfterSave();
\r
103 sleep(KEY_PAUSE_TIME_MS);
\r
104 keyUpAndDown(Characters.CONTROL_DOWN);
\r
105 sleep(KEY_PAUSE_TIME_MS);
\r
106 keyUpAndDown(Characters.CONTROL_DOWN); // min res
\r
107 sleep(KEY_PAUSE_TIME_MS);
\r
108 trackBallClick(); // out of res menu
\r
109 sleep(KEY_PAUSE_TIME_MS);
\r
110 trackBallClick(); // into res menu
\r
111 sleep(KEY_PAUSE_TIME_MS);
\r
112 keyUpAndDown(Characters.CONTROL_UP);
\r
113 sleep(KEY_PAUSE_TIME_MS);
\r
114 keyUpAndDown(Characters.CONTROL_UP); // max res
\r
115 sleep(KEY_PAUSE_TIME_MS);
\r
116 trackBallClick(); // out of res menu
\r
117 sleep(KEY_PAUSE_TIME_MS);
\r
118 keyUpAndDown(Characters.ESCAPE); // out of options
\r
119 sleep(KEY_PAUSE_TIME_MS);
\r
120 trackBallClick(); // yes to changes, even if there werent really any!
\r
121 Log.info("Finished setting resolution to max.");
\r
125 * Sets the camera resolution to it's maximum.
\r
126 * Note: currently disabled.
\r
128 private static void setMinResolution() {
\r
129 Log.info("Setting resolution to min.");
\r
130 accessResolutionMenu();
\r
131 sleep(KEY_PAUSE_TIME_MS);
\r
132 keyUpAndDown(Characters.CONTROL_UP);
\r
133 sleep(KEY_PAUSE_TIME_MS);
\r
134 keyUpAndDown(Characters.CONTROL_UP); // max res
\r
135 sleep(KEY_PAUSE_TIME_MS);
\r
136 trackBallClick(); // out of res menu
\r
137 sleep(KEY_PAUSE_TIME_MS);
\r
138 trackBallClick(); // into res menu
\r
139 sleep(KEY_PAUSE_TIME_MS);
\r
140 keyUpAndDown(Characters.CONTROL_DOWN);
\r
141 sleep(KEY_PAUSE_TIME_MS);
\r
142 keyUpAndDown(Characters.CONTROL_DOWN); // min res
\r
143 sleep(KEY_PAUSE_TIME_MS);
\r
144 trackBallClick(); // out of res menu
\r
145 sleep(KEY_PAUSE_TIME_MS);
\r
146 keyUpAndDown(Characters.ESCAPE); // out of options
\r
147 trackBallClick(); // yes to changes, even if there werent really any!
\r
150 private static void accessResolutionMenu() {
\r
151 keyUpAndDown(Characters.CONTROL_MENU);
\r
152 sleep(KEY_PAUSE_TIME_MS);
\r
153 keyUpAndDown(Characters.CONTROL_DOWN);
\r
154 sleep(KEY_PAUSE_TIME_MS);
\r
156 sleep(KEY_PAUSE_TIME_MS);
\r
157 keyUpAndDown(Characters.CONTROL_DOWN);
\r
158 sleep(KEY_PAUSE_TIME_MS);
\r
159 keyUpAndDown(Characters.CONTROL_DOWN);
\r
160 sleep(KEY_PAUSE_TIME_MS);
\r
164 private static void accessResolutionMenuAfterSave() {
\r
165 keyUpAndDown(Characters.CONTROL_MENU);
\r
166 keyUpAndDown(Characters.CONTROL_DOWN, 6, 0); // seems to be down 6 items on bb and 4 on simulator
\r
168 keyUpAndDown(Characters.CONTROL_DOWN);
\r
169 keyUpAndDown(Characters.CONTROL_DOWN);
\r
174 * Puts the current thread to sleep for a given amount of time.
\r
176 private static void sleep(int time) {
\r
178 Thread.sleep(time);
\r
179 } catch (InterruptedException ie) {
\r
185 private static void trackBallClick() {
\r
186 EventInjector.invokeEvent(
\r
187 new EventInjector.NavigationEvent(EventInjector.NavigationEvent.NAVIGATION_CLICK, 0, 0, 1));
\r
188 EventInjector.invokeEvent(
\r
189 new EventInjector.NavigationEvent(EventInjector.NavigationEvent.NAVIGATION_UNCLICK, 0, 0, 1));
\r
193 * Sends system level key events a given number of times with the given delay between them.
\r
195 private static void keyUpAndDown(char character, int times, int delay) {
\r
196 for (int i = 0; i < times; i++) {
\r
197 keyUpAndDown(character);
\r
205 * Sends one system level key event.
\r
207 private static void keyUpAndDown(char character) {
\r
208 EventInjector.invokeEvent(new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_DOWN, character, 0, 1));
\r
209 EventInjector.invokeEvent(new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_UP, character, 0, 1));
\r