"Fire" button now triggers decoding
[zxing.git] / javame / src / com / google / zxing / client / j2me / ZXingMIDlet.java
1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.client.j2me;
18
19 import com.google.zxing.MonochromeBitmapSource;
20 import com.google.zxing.MultiFormatReader;
21 import com.google.zxing.Reader;
22 import com.google.zxing.ReaderException;
23 import com.google.zxing.Result;
24
25 import javax.microedition.lcdui.Alert;
26 import javax.microedition.lcdui.AlertType;
27 import javax.microedition.lcdui.Canvas;
28 import javax.microedition.lcdui.Command;
29 import javax.microedition.lcdui.CommandListener;
30 import javax.microedition.lcdui.Display;
31 import javax.microedition.lcdui.Displayable;
32 import javax.microedition.lcdui.Graphics;
33 import javax.microedition.lcdui.Image;
34 import javax.microedition.media.Manager;
35 import javax.microedition.media.MediaException;
36 import javax.microedition.media.Player;
37 import javax.microedition.media.control.VideoControl;
38 import javax.microedition.midlet.MIDlet;
39 import javax.microedition.midlet.MIDletStateChangeException;
40 import java.io.IOException;
41
42 /**
43  * <p>The actual reader application {@link MIDlet}.</p>
44  *
45  * @author Sean Owen (srowen@google.com)
46  */
47 public final class ZXingMIDlet extends MIDlet {
48
49   private Player player;
50   private VideoControl videoControl;
51
52   protected void startApp() throws MIDletStateChangeException {
53     try {
54       player = Manager.createPlayer("capture://video");
55       player.realize();
56       videoControl = (VideoControl) player.getControl("VideoControl");
57       Displayable canvas = new VideoCanvas();
58       videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);
59       videoControl.setDisplayLocation(0, 0);
60       videoControl.setDisplaySize(canvas.getWidth(), canvas.getHeight());
61       videoControl.setVisible(true);
62       /*
63       FocusControl focusControl = (FocusControl)
64           player.getControl("javax.microedition.amms.control.FocusControl");
65       if (focusControl != null) {
66         if (focusControl.isAutoFocusSupported()) {
67           focusControl.setFocus(FocusControl.AUTO);
68         }
69         if (focusControl.isMacroSupported()) {
70           focusControl.setMacro(true);
71         }
72       } else {
73         System.out.println("FocusControl not supported");
74       }
75        */
76       Display.getDisplay(this).setCurrent(canvas);
77       player.start();
78     } catch (IOException ioe) {
79       throw new MIDletStateChangeException(ioe.toString());
80     } catch (MediaException me) {
81       throw new MIDletStateChangeException(me.toString());
82     }
83   }
84
85   protected void pauseApp() {
86     if (player != null) {
87       try {
88         player.stop();
89       } catch (MediaException me) {
90         // continue?
91         showError(me);        
92       }
93     }
94   }
95
96   protected void destroyApp(boolean unconditional) {
97     if (player != null) {
98       player.close();
99       player = null;
100       videoControl = null;
101     }
102   }
103
104   // Convenience methods to show dialogs
105
106   private void showAlert(String title, String text) {
107     Alert alert = new Alert(title, text, null, AlertType.INFO);
108     alert.setTimeout(Alert.FOREVER);
109     showAlert(alert);
110   }
111
112   private void showError(Throwable t) {
113     showAlert(new Alert("Error", t.getMessage(), null, AlertType.ERROR));
114   }
115
116   private void showAlert(Alert alert) {
117     Display display = Display.getDisplay(this);
118     display.setCurrent(alert, display.getCurrent());
119   }
120
121   private class VideoCanvas extends Canvas implements CommandListener {
122     private final Command decode = new Command("Decode", Command.SCREEN, 1);
123     private final Command exit = new Command("Exit", Command.EXIT, 1);
124     private VideoCanvas() {
125       addCommand(decode);
126       addCommand(exit);
127       setCommandListener(this);
128     }
129     protected void paint(Graphics graphics) {
130       // do nothing
131     }
132     protected void keyPressed(int keyCode) {
133       if (FIRE == getGameAction(keyCode)) {
134         new SnapshotThread().start();
135       }
136     }
137     public void commandAction(Command command, Displayable displayable) {
138       if (command.equals(decode)) {
139         new SnapshotThread().start();
140       } else if (command.equals(exit)) {
141         destroyApp(false);
142         notifyDestroyed();
143       }
144     }
145   }
146
147   // TODO make sure we do not start two threads at once
148   private class SnapshotThread extends Thread {
149     public void run() {
150       try {
151         player.stop();
152         byte[] snapshot = videoControl.getSnapshot(null);
153         Image capturedImage = Image.createImage(snapshot, 0, snapshot.length);
154         MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
155         Reader reader = new MultiFormatReader();
156         Result result = reader.decode(source);
157         showAlert("Barcode detected", result.getText());
158       } catch (ReaderException re) {
159         showError(re);
160       } catch (MediaException me) {
161         showError(me);
162       } catch (Throwable t) {
163         showError(t);
164       } finally {
165         try {
166           player.start();
167         } catch (MediaException me) {
168           // continue?
169           showError(me);
170         }
171       }
172
173     }
174   }
175
176 }