package edu.cmu.pocketsphinx.demo;

import java.util.Date;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class PocketSphinxDemo extends Activity implements OnTouchListener, RecognitionListener {
	static {
		System.loadLibrary("pocketsphinx_jni");
	}
	/**
	 * Recognizer task, which runs in a worker thread.
	 */
	RecognizerTask rec;
	/**
	 * Thread in which the recognizer task runs.
	 */
	Thread rec_thread;
	/**
	 * Time at which current recognition started.
	 */
	Date start_date;
	/**
	 * Number of seconds of speech.
	 */
	float speech_dur;
	/**
	 * Progress dialog for final recognition.
	 */
	ProgressDialog rec_dialog;
	/**
	 * Performance counter view.
	 */
	TextView performance_text;
	/**
	 * Editable text view.
	 */
	EditText edit_text;
	
	/**
	 * Respond to touch events on the Speak button.
	 * 
	 * This allows the Speak button to function as a "push and hold" button, by
	 * triggering the start of recognition when it is first pushed, and the end
	 * of recognition when it is released.
	 * 
	 * @param v
	 *            View on which this event is called
	 * @param event
	 *            Event that was triggered.
	 */
	public boolean onTouch(View v, MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			start_date = new Date();
			this.rec.start();
			break;
		case MotionEvent.ACTION_UP:
			Date end_date = new Date();
			long nmsec = end_date.getTime() - start_date.getTime();
			this.speech_dur = (float)nmsec / 1000;
			this.rec_dialog = ProgressDialog.show(PocketSphinxDemo.this, "", "Recognizing speech...", true);
			this.rec_dialog.setCancelable(false);
			this.rec.stop();
			break;
		default:
			;
		}
		/* Let the button handle its own state */
		return false;
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		this.rec = new RecognizerTask();
		this.rec_thread = new Thread(this.rec);
		Button b = (Button) findViewById(R.id.Button01);
		b.setOnTouchListener(this);
		this.performance_text = (TextView) findViewById(R.id.PerformanceText);
		this.edit_text = (EditText) findViewById(R.id.EditText01);
		this.rec.setRecognitionListener(this);
		this.rec_thread.start();
	}

	/** Called when partial results are generated. */
	@Override
	public void onPartialResults(Bundle b) {
		final PocketSphinxDemo that = this;
		final String hyp = b.getString("hyp");
		that.edit_text.post(new Runnable() {
			public void run() {
				that.edit_text.setText(hyp);
			}
		});
	}

	/** Called with full results are generated. */
	@Override
	public void onResults(Bundle b) {
		final String hyp = b.getString("hyp");
		final PocketSphinxDemo that = this;
		this.edit_text.post(new Runnable() {
			public void run() {
				that.edit_text.setText(hyp);
				Date end_date = new Date();
				long nmsec = end_date.getTime() - that.start_date.getTime();
				float rec_dur = (float)nmsec / 1000;
				that.performance_text.setText(String.format("%.2f seconds %.2f xRT",
															that.speech_dur,
															rec_dur / that.speech_dur));
				that.rec_dialog.dismiss();				
			}
		});
	}

	@Override
	public void onError(int err) {
		final PocketSphinxDemo that = this;
		that.edit_text.post(new Runnable() {
			public void run() {
				that.rec_dialog.dismiss();
			}
		});
	}
}
@@ -143,16 +143,41 @@
 Bundle;%0A
+import android.util.Log;%0A
 import a
@@ -201,16 +201,16 @@
 nEvent;%0A
-
 import a
@@ -813,24 +813,76 @@
 h_dur;%0A%09/**%0A
+%09 * Are we listening?%0A%09 */%0A%09boolean listening;%0A%09/**%0A
 %09 * Progress
@@ -1594,24 +1594,50 @@
 new Date();%0A
+%09%09%09this.listening = true;%0A
 %09%09%09this.rec.
@@ -1817,16 +1817,93 @@
 / 1000;%0A
+%09%09%09if (this.listening) %7B%0A%09%09%09%09Log.d(getClass().getName(), %22Showing Dialog%22);%0A%09
 %09%09%09this.
@@ -1993,24 +1993,25 @@
 , true);%0A%09%09%09
+%09
 this.rec_dia
@@ -2036,16 +2036,49 @@
 false);%0A
+%09%09%09%09this.listening = false;%0A%09%09%09%7D%0A
 %09%09%09this.
@@ -2444,16 +2444,42 @@
 s.rec);%0A
+%09%09this.listening = false;%0A
 %09%09Button
@@ -3605,16 +3605,66 @@
 _dur));%0A
+%09%09%09%09Log.d(getClass().getName(), %22Hiding Dialog%22);%0A
 %09%09%09%09that
@@ -3685,20 +3685,16 @@
 smiss();
-%09%09%09%09
 %0A%09%09%09%7D%0A%09%09

Add a latch thingy to the dialog because we sometimes get spurious button release events (or they occur out of order with the result notification, or something)