SnapshotThread now Runnable instead of a Thread, to dodge an odd override problem...
[zxing.git] / javame / src / com / google / zxing / client / j2me / SnapshotThread.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.Image;
26 import javax.microedition.media.MediaException;
27 import javax.microedition.media.Player;
28 import javax.microedition.media.control.VideoControl;
29
30 /**
31  * Thread which does the work of capturing a frame and decoding it.
32  *
33  * @author Sean Owen (srowen@google.com)
34  */
35 final class SnapshotThread implements Runnable {
36
37   private final ZXingMIDlet zXingMIDlet;
38   private final Object waitLock;
39   private boolean done;
40
41   SnapshotThread(ZXingMIDlet zXingMIDlet) {
42     this.zXingMIDlet = zXingMIDlet;
43     waitLock = new Object();
44     done = false;
45   }
46
47   void continueRun() {
48     synchronized (waitLock) {
49       waitLock.notifyAll();
50     }
51   }
52
53   private void waitForSignal() {
54     synchronized (waitLock) {
55       try {
56         waitLock.wait();
57       } catch (InterruptedException ie) {
58         // continue
59       }
60     }
61   }
62
63   void stop() {
64     done = true;
65     continueRun();
66   }
67
68   public void run() {
69     Player player = zXingMIDlet.getPlayer();
70     do {
71       waitForSignal();
72       try {
73         AdvancedMultimediaManager.setFocus(player);
74         byte[] snapshot = takeSnapshot();
75         Image capturedImage = Image.createImage(snapshot, 0, snapshot.length);
76         MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
77         Reader reader = new MultiFormatReader();
78         Result result = reader.decode(source);
79         zXingMIDlet.handleDecodedText(result);
80       } catch (ReaderException re) {
81         // Show a friendlier message on a mere failure to read the barcode
82         zXingMIDlet.showError("Sorry, no barcode was found.");
83       } catch (MediaException me) {
84         zXingMIDlet.showError(me);
85       } catch (RuntimeException re) {
86         zXingMIDlet.showError(re);
87       }
88     } while (!done);
89   }
90
91   private byte[] takeSnapshot() throws MediaException {
92     VideoControl videoControl = zXingMIDlet.getVideoControl();
93     byte[] snapshot = null;
94     try {
95       snapshot = videoControl.getSnapshot(null);
96     } catch (MediaException me) {
97     }
98     if (snapshot == null) {
99       // Fall back on JPEG; seems that some cameras default to PNG even
100       // when PNG isn't supported!
101       snapshot = videoControl.getSnapshot("encoding=jpeg");
102       if (snapshot == null) {
103         throw new MediaException("Can't obtain a snapshot");
104       }
105     }
106     return snapshot;
107   }
108
109 }