<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hdelossantos.com&#187; School</title>
	<atom:link href="http://www.hdelossantos.com/category/school/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hdelossantos.com</link>
	<description>Tales of the Wisconsin Experience</description>
	<lastBuildDate>Sat, 21 Jan 2012 19:54:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Writing a *NIX Shell in C</title>
		<link>http://www.hdelossantos.com/2012/01/21/writing-a-nix-shell-in-c/</link>
		<comments>http://www.hdelossantos.com/2012/01/21/writing-a-nix-shell-in-c/#comments</comments>
		<pubDate>Sat, 21 Jan 2012 19:51:52 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=707</guid>
		<description><![CDATA[The shell will take in a maximum line length of 512 characters. Additionally it will support batch execution of commands specified in an input file. To call the shell in batch execution mode execute as: The shell will fork and execute each process as a child process so that in the event of an infinite [...]]]></description>
			<content:encoded><![CDATA[<p>The shell will take in a maximum line length of 512 characters. Additionally it will support batch execution of commands specified in an input file. To call the shell in batch execution mode execute as:</p>
<pre class="brush: plain; title: ; notranslate">
./shell &lt;input file&gt;
</pre>
<p>The shell will fork and execute each process as a child process so that in the event of an infinite loop the terminal can still respond to the SIGTERM command. Output can be piped to an external file using the &#8220;<b>></b>&#8221; operator. In the event that the destination file is not found, it is created with the permissions <b>755</b>. The permissions and line length can be changed in the parameters in the header file below.<br />
<span id="more-707"></span><br />
The header files declares the two functions which will be used. The <b>trimspace</b> function trims a given string of leading and trailing spaces. The <b>executecmd</b> function is given a command line to execute.</p>
<p><b>shell.h</b>:</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;stdio.h&gt;
#include &lt;assert.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;unistd.h&gt;
#include &lt;ctype.h&gt;

#define MAX_ARGS 512
#define PERMS 0755

char *trimspace(char *str);
void executecmd(char *commands);
</pre>
<p><b>shell.c</b>:</p>
<pre class="brush: cpp; title: ; notranslate">
#include &quot;537sh.h&quot;

// Trim function from code @:
// http://goo.gl/gVRb
char *trimspace(char *str){
	char *last;

	while(isspace(*str)) {
		 str++;
	}
	if(*str == 0) {
		return str;
	}

	last = str + strlen(str) - 1;
	while(last &gt; str &amp;&amp; isspace(*last)) {
		 last--;
	}

	*(last + 1) = 0;

	return str;
}
</pre>
<p>The <b>executecmd</b> function:</p>
<p>This function sets up the default error message to output on any type of error, and a variable to store the child process ID information. </p>
<pre class="brush: cpp; title: ; notranslate">
void executecmd(char *commands) {
	char error_message[30] = &quot;An error has occurred\n&quot;;
	pid_t child_pid;
</pre>
<p>It then checks to see if the &#8220;<b>+</b>&#8221; operator is used. This operator is used to feed more than one command per line. It works similar to the &#8220;<b>&#038;&#038;</b>&#8221; operator in the Linux shell. </p>
<pre class="brush: cpp; title: ; notranslate">
	// Split the input line if the multiple cmd operator is used
	char *argv_parent[MAX_ARGS];
	int more_args_parent = 1;
	int argv_index_parent = 0;

	argv_parent[argv_index_parent++] = strtok(commands, &quot;+&quot;);
	while(more_args_parent) {
		argv_parent[argv_index_parent++] = strtok(NULL, &quot;+&quot;);
		if(argv_parent[argv_index_parent - 1] == NULL) more_args_parent = 0;
	}
</pre>
<p>Since every command can have a redirect to an output file &#8220;<b>+</b>&#8220;, or a sorted redirect to an output file &#8220;<b>==</b>&#8221; it must check every individual command which was separated using the string tokenizer <b>strtok</b>.</p>
<pre class="brush: cpp; title: ; notranslate">
	// For every split command fork &amp; exec
	int i;
	for(i = 0; i &lt; argv_index_parent; i++) {
		// Variables
		char *redirect = (char*) malloc(512);
		char *redirraw = NULL;
		char *sortredirraw = NULL;
		char *redirect_args[MAX_ARGS];
		int more_args_redirect = 1;
		int index_redirect = 0;

		if(argv_parent[i] != NULL) {
			redirraw = strchr(argv_parent[i], '&gt;');
			sortredirraw = strstr(argv_parent[i], &quot;==&quot;);

			if(redirraw != NULL) {
				redirect_args[index_redirect++] = strtok(argv_parent[i], &quot;&gt;&quot;);
				while(more_args_redirect) {
					redirect_args[index_redirect++] = strtok(NULL, &quot;&gt;&quot;);
					if(redirect_args[index_redirect - 1] == NULL) more_args_redirect = 0;
				}
				if(redirect_args[1] != NULL) {
					// There must be a redirect location
					redirect = trimspace(redirect_args[1]);
				}
			}
			else if(sortredirraw != NULL) {
				redirect_args[index_redirect++] = strtok(argv_parent[i], &quot;==&quot;);
				while(more_args_redirect) {
					redirect_args[index_redirect++] = strtok(NULL, &quot;==&quot;);
					if(redirect_args[index_redirect - 1] == NULL) more_args_redirect = 0;
				}
				if(redirect_args[1] != NULL) {
					// There must be a redirect location
					redirect = trimspace(redirect_args[1]);
				}
			}
		}
</pre>
<p>The shell implements 3 built in commands <strong>exit, cd,</strong> and <strong>pwd</strong>. If the <strong>exit</strong> command is found anywhere in a line containing multiple commands, the shell child process immediately exits and execution of the commands following the current one are not carried out. If the <strong>cd</strong> command is executed without any parameters, the shell switches to the user&#8217;s home directory, detected with the <strong>getenv(&#8220;HOME&#8221;)</strong> system call, much like <strong>cd ~</strong> would do in UNIX. If a path is specified, the current directory is changed to it using the <strong>chdir</strong> system call, unless the path does not exist, in which case an error is displayed. The <strong>pwd</strong> command utilizes the <strong>getcwd</strong> system call to get the current working directory and displays it on the screen.</p>
<pre class="brush: cpp; title: ; notranslate">
		/**
		 * BUILT IN COMMANDS
		 **/

		// EXIT
		if(argv_parent[i] != NULL &amp;&amp; strcmp(trimspace(argv_parent[i]), &quot;exit&quot;) == 0) exit(0);

		// PWD
		else if(argv_parent[i] != NULL &amp;&amp; strncmp(trimspace(argv_parent[i]), &quot;pwd&quot;, 3) == 0) {
			if(strcmp(trimspace(argv_parent[i]), &quot;pwd&quot;) == 0) {
			char directory[MAX_ARGS];
				getcwd(directory, MAX_ARGS);
				strcat(directory, &quot;\n&quot;);
				write(STDOUT_FILENO, directory, strlen(directory));
			}
			else {
				write(STDERR_FILENO, error_message, strlen(error_message));
			}
		}

		// CD
		else if(argv_parent[i] != NULL &amp;&amp; strncmp(trimspace(argv_parent[i]), &quot;cd&quot;, 2) == 0) {
			if(strlen(argv_parent[i]) &gt; 3) {
				// Split the string @ char 3 &amp; trim white spaces
				char *directory = (char*) malloc(strlen(argv_parent[i])-2);
				strncpy(directory, trimspace(argv_parent[i])+2, strlen(argv_parent[i]));
				directory = trimspace(directory);
				if(chdir(directory) == -1) {
					write(STDERR_FILENO, error_message, strlen(error_message));
				}
			}
			else {
				chdir(getenv(&quot;HOME&quot;));
			}
		}
</pre>
<p>All other commands are handled by the <strong>execvp</strong> system call. Since the output of any of these commands can be redirected, we must check to see if the redirection character has been detected. If it has, then we know that we need to get two arguments rather than 1 from the array of commands. Each command is then executed as a child process using the <strong>fork</strong> system call. For the piping commands, the output is redirected to the specified file using the <strong>dup2</strong> system call. For the sorted redirect, a pipe must be created so that the output of the command is fed into the input of the sort command. The output of the sort is then sent to the external file specified.</p>
<pre class="brush: cpp; title: ; notranslate">
		/**
		 * SYSTEM COMMANDS
		 **/
		else {
			// Check if this is an empty command, if it is do nothing
			if(argv_parent[i] != NULL &amp;&amp; strcmp(trimspace(argv_parent[i]), &quot;&quot;) != 0) {

				// Sorted redirect variables
				int fd[2];
				int secondChild_pid = -1; // Neg means it failed

				if(redirect != NULL &amp;&amp; strlen(redirect) &gt; 0 &amp;&amp; strstr(redirect, &quot; &quot;) != NULL) {
					// There must be two output files separated by space
					write(STDERR_FILENO, error_message, strlen(error_message));
					exit(0);
				}

				if(sortredirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) &gt; 0)
					pipe(fd);

				child_pid = fork();
				if(child_pid == 0) {
					char *argv[MAX_ARGS];
					int more_args = 1;
					int argv_index = 0;

					if(redirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) &gt; 0) {
						int file = open(redirect, O_CREAT | O_WRONLY, PERMS);
						if(file == -1) {
							// File not found
							write(STDERR_FILENO, error_message, strlen(error_message));
							exit(1);
						}
						dup2(file, 1);
					}
					else if(redirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) == 0) {
						write(STDERR_FILENO, error_message, strlen(error_message));
						exit(1);
					}
					else if(sortredirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) &gt; 0) {
						close(fd[0]);
						dup2(fd[1], STDOUT_FILENO);
					}
					else if(sortredirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) == 0) {
						write(STDERR_FILENO, error_message, strlen(error_message));
						exit(1);
					}

					// Determine the command arguments
					argv[argv_index++] = strtok(argv_parent[i], &quot; &quot;);
					while(more_args) {
						argv[argv_index++] = strtok(NULL, &quot; &quot;);
						if(argv[argv_index - 1] == NULL) more_args = 0;
					}
					if(execvp(argv[0], argv)) {
						// This executes if there's an error
						write(STDERR_FILENO, error_message, strlen(error_message));
						exit(0);
					}
				}
				else if(child_pid &lt; 0) {
					fprintf(stderr, &quot;Fork Failed&quot;);
					exit(1);
				}
				else {
					// Code executed by parent
					if(sortredirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) &gt; 0) {
						secondChild_pid = fork();
						if(secondChild_pid == 0) {
						// Child code
							close(fd[1]);
							dup2(fd[0], STDIN_FILENO);
							int file = open(redirect, O_CREAT | O_WRONLY, PERMS);

							if(file == -1) {
								// File not found
								write(STDERR_FILENO, error_message, strlen(error_message));
								exit(1);
							}
							else
								dup2(file, STDOUT_FILENO);

							char *sortarg[2] = {&quot;sort&quot;, NULL};

							// SORT
							execvp(sortarg[0], sortarg);
							write(STDERR_FILENO, error_message, strlen(error_message));
							exit(0);
						}
						else if(child_pid &lt; 0) {
							fprintf(stderr, &quot;Fork Failed&quot;);
							exit(1);
						}
					}
					close(fd[1]);
					if(sortredirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) &gt; 0)
						close(fd[0]);
					waitpid(child_pid, NULL, 0);
					if(sortredirraw != NULL &amp;&amp; redirect != NULL &amp;&amp; strlen(redirect) &gt; 0)
						waitpid(secondChild_pid, NULL, 0);
				}
			}
		}
	}
}
</pre>
<p><b>main</b> function:<br />
The main function determines if the application will run in shell mode, or batch mode. In batch mode it takes the line inputs from a file, while shell mode loops the prompt until the exit command is entered. If more than one input file are specified or the input file is not found, an error is displayed.</p>
<pre class="brush: cpp; title: ; notranslate">
int main (int argc, char *argv[]) {
	char commands[MAX_ARGS];
	char error_message[30] = &quot;An error has occurred\n&quot;;
	char cmdline[8] = &quot;537sh% &quot;;

	if(argc == 1) {
		while(strcmp(trimspace(commands), &quot;exit&quot;) != 0) {
			// STDIN
			write(STDOUT_FILENO, cmdline, strlen(cmdline));
			fgets(commands, MAX_ARGS, stdin);
			if(strchr(commands, '\n') ==  NULL) {
				// Output an error since the line was truncated
				write(STDERR_FILENO, error_message, strlen(error_message));
			}
			else {
				// Execute the command if the line is good
				executecmd(commands);
			}
		}
	}
	else if(argc == 2){
		// Batch input
		FILE *input = fopen(argv[1], &quot;r&quot;);
		if(input != NULL) {
			while(fgets(commands, MAX_ARGS, input) != NULL) {
				if(strchr(commands, '\n') == NULL)
					strcat(commands, &quot;\n&quot;);
				write(STDOUT_FILENO, commands, strlen(commands));
				executecmd(commands);
			}
		}
		else {
			write(STDERR_FILENO, error_message, strlen(error_message));
			exit(1);
		}
	}
	else {
		write(STDERR_FILENO, error_message, strlen(error_message));
		exit(1);
	}

	return 0;

}
</pre>
<p><!--adsensestart--></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2012/01/21/writing-a-nix-shell-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;ve earned my Android Badge :)</title>
		<link>http://www.hdelossantos.com/2009/11/08/ive-earned-my-android-badge/</link>
		<comments>http://www.hdelossantos.com/2009/11/08/ive-earned-my-android-badge/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 04:13:07 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[developer]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[SHPE]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=467</guid>
		<description><![CDATA[After having been developing Android applications for 2 months I like to think that I have earned my Android badge. Last week at the SHPE conference I was given an android sticker at the Google booth, which now adorns my laptop. Of course calling myself a developer makes me think of:]]></description>
			<content:encoded><![CDATA[<p>After having been developing Android applications for 2 months I like to think that I have earned my Android badge. Last week at the <a href="http://oneshpe.shpe.org/wps/portal/national">SHPE</a> conference I was given an android sticker at the Google booth, which now adorns my laptop.</p>
<p><a class="lightview" href="http://www.hdelossantos.com/blog/wp-content/uploads/2009/11/DSC01505-1024x768.jpg"><img src="http://www.hdelossantos.com/blog/wp-content/uploads/2009/11/DSC01505-300x225.jpg" alt="My Laptop&#039;s Android" title="My Laptop&#039;s Android" width="300" height="225" class="aligncenter size-large wp-image-468" /></a></p>
<p>Of course calling myself a <em>developer</em> makes me think of:</p>
<div align="center"><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/8zEQhhaJsU4&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/8zEQhhaJsU4&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></div>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2009/11/08/ive-earned-my-android-badge/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Talking Twitter</title>
		<link>http://www.hdelossantos.com/2009/10/10/talking-twitter/</link>
		<comments>http://www.hdelossantos.com/2009/10/10/talking-twitter/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 05:58:43 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Computer Engineering]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Sample Work]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[c language]]></category>
		<category><![CDATA[code assignment]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[device programming]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[hanly de los santos]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[mobile device]]></category>
		<category><![CDATA[POST]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[register]]></category>
		<category><![CDATA[show]]></category>
		<category><![CDATA[speech recognition]]></category>
		<category><![CDATA[speech-to-text]]></category>
		<category><![CDATA[tea]]></category>
		<category><![CDATA[text-to-speech]]></category>
		<category><![CDATA[text2speech]]></category>
		<category><![CDATA[TTS library]]></category>
		<category><![CDATA[tv]]></category>
		<category><![CDATA[tweet]]></category>
		<category><![CDATA[tweets]]></category>
		<category><![CDATA[twitta]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=437</guid>
		<description><![CDATA[A week ago, for my mobile device programming class, I had to add text-to-speech and speech-to-text capabilities to a freely available Android program called Twitta. The features I added were very crudely superimposed on the Twitta interface, therefore this edit is by no means polished or intended for production usage. There are 3 button &#8220;S&#8221;, [...]]]></description>
			<content:encoded><![CDATA[<p>A week ago, for my mobile device programming class, I had to add text-to-speech and speech-to-text capabilities to a freely available Android program called <a href="http://code.google.com/p/twitta/">Twitta</a>. The features I added were very crudely superimposed on the Twitta interface, therefore this edit is by no means polished or intended for production usage.</p>
<p>There are 3 button &#8220;S&#8221;, &#8220;X&#8221;, and &#8220;R&#8221;. &#8220;S&#8221; starts the playback of all of the tweets which are currently displayed on the screen. Once the user scrolls down and new tweets appear on the screen the button can be pressed again and only the new ones will be read. &#8220;X&#8221; stops the playback of the messages. &#8220;R&#8221; prompts the user to speak their tweet. The google speech to text engine converts it to text and is displayed on the edit bar. If the message was wrong, pressing &#8220;R&#8221; again clears it and prompts for new speech. The message can also be edited with the keyboard. Below is a video of the application in action:</p>
<div align="center">
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/gnMUc1TuxpE&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/gnMUc1TuxpE&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></div>
<p><span id="more-437"></span></p>
<p>The source code is below. The sections edited by me are enclosed in comments.</p>
<pre class="brush: plain; title: ; notranslate">
/*
 * Copyright (C) 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dart.android.twitter;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.*;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;

import com.dart.android.twitter.TwitterApi.ApiException;
import com.dart.android.twitter.TwitterApi.AuthException;
import com.google.android.photostream.UserTask;
import com.google.tts.TTS;
import com.google.tts.TTS.InitListener;

public class TwitterActivity extends BaseActivity implements InitListener{
  private static final String TAG = &quot;TwitterActivity&quot;;

  //BEGIN: Added by Hanly De Los Santos
  //Speech
  private static boolean ttsReady = false;
  private static TTS myTTS;
  private static ConcurrentLinkedQueue&lt;String&gt; tweetStrings;
  private Button speak;
  private Button stop;
  private Button reco;
  private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
  //END: Added by Hanly De Los Santos

  // Views.
  private ListView mTweetList;
  private TweetAdapter mTweetAdapter;

  private TweetEdit mTweetEdit;
  private ImageButton mSendButton;

  private TextView mProgressText;

  // State.
  private int mState;

  private static final int STATE_ALL = 0;
  private static final int STATE_REPLIES = 1;

  // Tasks.
  private UserTask&lt;Void, Void, RetrieveResult&gt; mRetrieveTask;
  private UserTask&lt;Void, Void, SendResult&gt; mSendTask;
  private UserTask&lt;Void, Void, RetrieveResult&gt; mFollowersRetrieveTask;

  // Refresh data at startup if last refresh was this long ago or greater.
  private static final long REFRESH_THRESHOLD = 5 * 60 * 1000;

  // Refresh followers if last refresh was this long ago or greater.
  private static final long FOLLOWERS_REFRESH_THRESHOLD = 12 * 60 * 60 * 1000;

  private static final String LAUNCH_ACTION = &quot;com.dart.android.twitter.TWEETS&quot;;
  private static final String NEW_TWEET_ACTION = &quot;com.dart.android.twitter.NEW&quot;;

  private static final String EXTRA_TEXT = &quot;text&quot;;

  public static Intent createIntent(Context context) {
    Intent intent = new Intent(LAUNCH_ACTION);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    return intent;
  }

  public static Intent createNewTaskIntent(Context context) {
    Intent intent = createIntent(context);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    return intent;
  }

  public static Intent createNewTweetIntent(String text) {
    Intent intent = new Intent(NEW_TWEET_ACTION);
    intent.putExtra(EXTRA_TEXT, text);

    return intent;
  }

  private boolean isReplies() {
    return mState == STATE_REPLIES;
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //BEGIN: Added by Hanly De Los Santos

    //Initialize TTS Service
    myTTS = new TTS(this, this, true);
    tweetStrings = new ConcurrentLinkedQueue&lt;String&gt;();

    //END: Added by Hanly De Los Santos

    if (!getApi().isLoggedIn()) {
      Log.i(TAG, &quot;Not logged in.&quot;);
      handleLoggedOut();
      return;
    }

    setContentView(R.layout.main);

    Intent intent = getIntent();
    String action = intent.getAction();

    mState = mPreferences.getInt(
        Preferences.TWITTER_ACTIVITY_STATE_KEY, STATE_ALL);

    mTweetList = (ListView) findViewById(R.id.tweet_list);

    mTweetEdit = new TweetEdit((EditText) findViewById(R.id.tweet_edit),
        (TextView) findViewById(R.id.chars_text));
    mTweetEdit.setOnKeyListener(tweetEnterHandler);

    if (NEW_TWEET_ACTION.equals(action)) {
      mTweetEdit.setText(intent.getStringExtra(EXTRA_TEXT));
    }

    mProgressText = (TextView) findViewById(R.id.progress_text);

    mSendButton = (ImageButton) findViewById(R.id.send_button);
    mSendButton.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        doSend();
      }
    });

    //BEGIN: Added by Hanly De Los Santos
    // Speak Button
    this.speak = (Button)this.findViewById(R.id.Speak);
    this.speak.setOnClickListener(new OnClickListener() {

		@Override
		public void onClick(View v) {
			if(tweetStrings != null){
				new Thread(new Runnable(){
	        		public void run(){
		        		try{
		        			Speak startSpeak = new Speak();
		        	        while(!myTTS.isSpeaking()){
		        	        	for(int i=0; i&lt;tweetStrings.size(); i++){
		        	        		String speak = (String)tweetStrings.poll();
		        		        	startSpeak.speak(ttsReady, myTTS, speak);
		        		        	final String TAG = &quot;Hanly-Pop Out&quot;;
		        		            Log.v(TAG, speak);
		        		        }
		        	        }
		        		}
		        		catch(Exception e){}
	        		}
	        	}).start();
		    }
		}
    });

    this.stop = (Button)this.findViewById(R.id.Stop);
    this.stop.setOnClickListener(new OnClickListener() {

    	@Override
		public void onClick(View v) {
			Speak startSpeak = new Speak();
			startSpeak.stop(ttsReady, myTTS);
		}
    });

    //Start of speech recognition code
    this.reco = (Button)this.findViewById(R.id.Reco);
    this.reco.setOnClickListener(new OnClickListener(){

    	@Override
		public void onClick(View v) {
    		startVoiceRecognitionActivity();
		}
    });
    //END: Added by Hanly De Los Santos

    // Mark all as read.
    getDb().markAllTweetsRead();

    setupState();

    registerForContextMenu(mTweetList);

    boolean shouldRetrieve = false;

    long lastRefreshTime = mPreferences.getLong(
        Preferences.LAST_TWEET_REFRESH_KEY, 0);
    long nowTime = Utils.getNowTime();

    long diff = nowTime - lastRefreshTime;
    Log.i(TAG, &quot;Last refresh was &quot; + diff + &quot; ms ago.&quot;);

    if (diff &gt; REFRESH_THRESHOLD) {
      shouldRetrieve = true;
    } else if (Utils.isTrue(savedInstanceState, SIS_RUNNING_KEY)) {
      // Check to see if it was running a send or retrieve task.
      // It makes no sense to resend the send request (don't want dupes)
      // so we instead retrieve (refresh) to see if the message has posted.
      Log.i(TAG, &quot;Was last running a retrieve or send task. Let's refresh.&quot;);
      shouldRetrieve = true;
    }

    if (shouldRetrieve) {
      doRetrieve();
    }

    long lastFollowersRefreshTime = mPreferences.getLong(
        Preferences.LAST_FOLLOWERS_REFRESH_KEY, 0);

    diff = nowTime - lastFollowersRefreshTime;
    Log.i(TAG, &quot;Last followers refresh was &quot; + diff + &quot; ms ago.&quot;); 

    if (diff &gt; FOLLOWERS_REFRESH_THRESHOLD) {
      doRetrieveFollowers();
    }
  }

//BEGIN: Added by Hanly De Los Santos
  private void startVoiceRecognitionActivity() {
	  mTweetEdit.setText(&quot;&quot;);
	  Intent intent = new Intent(&quot;android.speech.action.RECOGNIZE_SPEECH&quot;);
	  startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == VOICE_RECOGNITION_REQUEST_CODE &amp;&amp; resultCode == RESULT_OK) {
          // Fill the list view with the strings the recognizer thought it could have heard
          ArrayList&lt;String&gt; matches = data.getStringArrayListExtra(
                  RecognizerIntent.EXTRA_RESULTS);
          try{
        	  Thread.currentThread().sleep(1000);//sleep for 1000 ms
        	}
        	catch(Exception ie){
        	//If this thread was interrupted by another thread
        	}
    	  Speak startSpeak = new Speak();
          String speak = &quot;Did you say &quot;+matches.toString();
          startSpeak.speak(ttsReady, myTTS, speak);
          mTweetEdit.setTextAndFocus(matches.toString().replaceAll(&quot;[\\]\\[]&quot;, &quot;&quot;));
          final String TAG = &quot;Hanly-Speak Result&quot;;
          Log.v(TAG, matches.toString());
      }

      super.onActivityResult(requestCode, resultCode, data);
  }
	//END: Added by Hanly De Los Santos
  @Override
  protected void onResume() {
    super.onResume();

    if (!getApi().isLoggedIn()) {
      Log.i(TAG, &quot;Not logged in.&quot;);
      handleLoggedOut();
      return;
    }
  }

  private void doRetrieveFollowers() {
    Log.i(TAG, &quot;Attempting followers retrieve.&quot;);

    if (mFollowersRetrieveTask != null
        &amp;&amp; mFollowersRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      Log.w(TAG, &quot;Already retrieving.&quot;);
    } else {
      mFollowersRetrieveTask = new FollowersTask().execute();
    }
  }

  private static final String SIS_RUNNING_KEY = &quot;running&quot;;

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (mRetrieveTask != null
        &amp;&amp; mRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      outState.putBoolean(SIS_RUNNING_KEY, true);
    } else if (mSendTask != null
        &amp;&amp; mSendTask.getStatus() == UserTask.Status.RUNNING) {
      outState.putBoolean(SIS_RUNNING_KEY, true);
    }
  }

  @Override
  protected void onRestoreInstanceState(Bundle bundle) {
    super.onRestoreInstanceState(bundle);

    mTweetEdit.updateCharsRemain();
  }

  @Override
  protected void onDestroy() {
    Log.i(TAG, &quot;onDestroy.&quot;);

    if (mSendTask != null &amp;&amp; mSendTask.getStatus() == UserTask.Status.RUNNING) {
      // Doesn't really cancel execution (we let it continue running).
      // See the SendTask code for more details.
      mSendTask.cancel(true);
    }

    if (mRetrieveTask != null
        &amp;&amp; mRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      mRetrieveTask.cancel(true);
    }

    // Don't need to cancel FollowersTask (assuming it ends properly).

    super.onDestroy();
  }

  // UI helpers.

  private void updateProgress(String progress) {
    mProgressText.setText(progress);
  }

  private void setupState() {
    Cursor cursor;

    if (isReplies()) {
      cursor = getDb().fetchReplies();
      setTitle(&quot;@&quot; + getApi().getUsername());
    } else {
      cursor = getDb().fetchAllTweets();
      setTitle(R.string.app_name);
    }

    startManagingCursor(cursor);

    mTweetAdapter = new TweetAdapter(this, cursor);
    mTweetList.setAdapter(mTweetAdapter);
  }

  private static final int CONTEXT_MORE_ID = 3;
  private static final int CONTEXT_REPLY_ID = 0;
  private static final int CONTEXT_RETWEET_ID = 1;
  private static final int CONTEXT_DM_ID = 2;

  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
      ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    AdapterView.AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
    Cursor cursor = (Cursor) mTweetAdapter.getItem(info.position);
    long userId = cursor.getLong(cursor
        .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER_ID));
    String user = cursor.getString(cursor
        .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER));

    menu.add(0, CONTEXT_MORE_ID, 0, user);
    menu.add(0, CONTEXT_REPLY_ID, 0, R.string.reply);
    menu.add(0, CONTEXT_RETWEET_ID, 0, R.string.retweet);

    MenuItem item = menu.add(0, CONTEXT_DM_ID, 0, R.string.dm);
    item.setEnabled(getDb().isFollower(userId));
  }

  @Override
  public boolean onContextItemSelected(MenuItem item) {
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    Cursor cursor = (Cursor) mTweetAdapter.getItem(info.position);

    if (cursor == null) {
      Log.w(TAG, &quot;Selected item not available.&quot;);
      return super.onContextItemSelected(item);
    }

    switch (item.getItemId()) {
    case CONTEXT_MORE_ID:
      String who = cursor.getString(
          cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER));
      launchActivity(UserActivity.createIntent(who));

      return true;
    case CONTEXT_REPLY_ID:
      int userIndex = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER);
      // TODO: this isn't quite perfect. It leaves extra empty spaces if you
      // perform the reply action again.
      String replyTo = &quot;@&quot; + cursor.getString(userIndex);
      String text = mTweetEdit.getText();
      text = replyTo + &quot; &quot; + text.replace(replyTo, &quot;&quot;);
      mTweetEdit.setTextAndFocus(text);

      return true;
    case CONTEXT_RETWEET_ID:
      String retweet = &quot;RT @&quot;
          + cursor.getString(cursor
              .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER))
          + &quot; &quot;
          + cursor.getString(cursor
              .getColumnIndexOrThrow(TwitterDbAdapter.KEY_TEXT));
      mTweetEdit.setTextAndFocus(retweet);

      return true;
    case CONTEXT_DM_ID:
      String user = cursor.getString(cursor
          .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER));
      launchActivity(DmActivity.createIntent(user));
      return true;
    default:
      return super.onContextItemSelected(item);
    }
  }

  private static class TweetAdapter extends CursorAdapter {

    public TweetAdapter(Context context, Cursor cursor) {
      super(context, cursor);

      mInflater = LayoutInflater.from(context);

      mUserTextColumn = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER);
      mTextColumn = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_TEXT);
      mProfileImageUrlColumn = cursor
          .getColumnIndexOrThrow(TwitterDbAdapter.KEY_PROFILE_IMAGE_URL);
      mCreatedAtColumn = cursor
          .getColumnIndexOrThrow(TwitterDbAdapter.KEY_CREATED_AT);
      mSourceColumn = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_SOURCE);

      mMetaBuilder = new StringBuilder();
    }

    private LayoutInflater mInflater;

    private int mUserTextColumn;
    private int mTextColumn;
    private int mProfileImageUrlColumn;
    private int mCreatedAtColumn;
    private int mSourceColumn;

    private StringBuilder mMetaBuilder;

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
      View view = mInflater.inflate(R.layout.tweet, parent, false);

      ViewHolder holder = new ViewHolder();
      holder.tweetUserText = (TextView) view.findViewById(R.id.tweet_user_text);
      holder.tweetText = (TextView) view.findViewById(R.id.tweet_text);
      holder.profileImage = (ImageView) view.findViewById(R.id.profile_image);
      holder.metaText = (TextView) view.findViewById(R.id.tweet_meta_text);
      view.setTag(holder);

      return view;
    }

    private static class ViewHolder {
      public TextView tweetUserText;
      public TextView tweetText;
      public ImageView profileImage;
      public TextView metaText;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
      ViewHolder holder = (ViewHolder) view.getTag();

      holder.tweetUserText.setText(cursor.getString(mUserTextColumn));
      Utils.setTweetText(holder.tweetText, cursor.getString(mTextColumn));

    //BEGIN: Added by Hanly De Los Santos
      String say = cursor.getString(mUserTextColumn)+&quot; said &quot;+cursor.getString(mTextColumn);

      while(!tweetStrings.contains(say))
    	  tweetStrings.add(say); 

    // END: Added by Hanly De Los Santos

      String profileImageUrl = cursor.getString(mProfileImageUrlColumn);

      if (!Utils.isEmpty(profileImageUrl)) {
        holder.profileImage.setImageBitmap(TwitterApplication.mImageManager.get(
            profileImageUrl));
      }

      try {
        Date createdAt = TwitterDbAdapter.DB_DATE_FORMATTER.parse(cursor
            .getString(mCreatedAtColumn));
        holder.metaText.setText(Tweet.buildMetaText(mMetaBuilder, createdAt,
            cursor.getString(mSourceColumn)));
      } catch (ParseException e) {
        Log.w(TAG, &quot;Invalid created at data.&quot;);
      }
    }

    public void refresh() {
      getCursor().requery();
    }

  }

  private void draw() {
    mTweetAdapter.refresh();
  }

  private void goTop() {
    mTweetList.setSelection(0);
  }

  private void enableEntry() {
    mTweetEdit.setEnabled(true);
    mSendButton.setEnabled(true);
  }

  private void disableEntry() {
    mTweetEdit.setEnabled(false);
    mSendButton.setEnabled(false);
  }

  // Actions.

  private void doSend() {
    if (mSendTask != null &amp;&amp; mSendTask.getStatus() == UserTask.Status.RUNNING) {
      Log.w(TAG, &quot;Already sending.&quot;);
    } else {
      String status = mTweetEdit.getText().toString();

      if (!Utils.isEmpty(status)) {
        mSendTask = new SendTask().execute();
      }
    }
  }

  private enum SendResult {
    OK, IO_ERROR, AUTH_ERROR, CANCELLED
  }

  private class SendTask extends UserTask&lt;Void, Void, SendResult&gt; {
    @Override
    public void onPreExecute() {
      onSendBegin();
    }

    @Override
    public SendResult doInBackground(Void... params) {
      try {
        String status = mTweetEdit.getText().toString();
        JSONObject jsonObject = getApi().update(status);
        Tweet tweet = Tweet.create(jsonObject);

        if (!Utils.isEmpty(tweet.profileImageUrl)) {
          // Fetch image to cache.
          try {
            getImageManager().put(tweet.profileImageUrl);
          } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
          }
        }

        getDb().createTweet(tweet, false);
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
        return SendResult.IO_ERROR;
      } catch (AuthException e) {
        Log.i(TAG, &quot;Invalid authorization.&quot;);
        return SendResult.AUTH_ERROR;
      } catch (JSONException e) {
        Log.w(TAG, &quot;Could not parse JSON after sending update.&quot;);
        return SendResult.IO_ERROR;
      } catch (ApiException e) {
        Log.e(TAG, e.getMessage(), e);
        return SendResult.IO_ERROR;
      }

      return SendResult.OK;
    }

    @Override
    public void onPostExecute(SendResult result) {
      if (isCancelled()) {
        // Canceled doesn't really mean &quot;canceled&quot; in this task.
        // We want the request to complete, but don't want to update the
        // activity (it's probably dead).
        return;
      }

      if (result == SendResult.AUTH_ERROR) {
        logout();
      } else if (result == SendResult.OK) {
        onSendSuccess();
      } else if (result == SendResult.IO_ERROR) {
        onSendFailure();
      }
    }
  }

  private void onSendBegin() {
    disableEntry();
    updateProgress(&quot;Updating status...&quot;);
  }

  private void onSendSuccess() {
    mTweetEdit.setText(&quot;&quot;);
    updateProgress(&quot;&quot;);
    enableEntry();
    draw();
    goTop();
  }

  private void onSendFailure() {
    updateProgress(&quot;Unable to update status&quot;);
    enableEntry();
  }

  private void doRetrieve() {
    Log.i(TAG, &quot;Attempting retrieve.&quot;);

    if (mRetrieveTask != null
        &amp;&amp; mRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      Log.w(TAG, &quot;Already retrieving.&quot;);
    } else {
      mRetrieveTask = new RetrieveTask().execute();
    }
  }

  private void onRetrieveBegin() {
    updateProgress(&quot;Refreshing...&quot;);
  }

  private enum RetrieveResult {
    OK, IO_ERROR, AUTH_ERROR, CANCELLED
  }

  private class RetrieveTask extends UserTask&lt;Void, Void, RetrieveResult&gt; {
    @Override
    public void onPreExecute() {
      onRetrieveBegin();
    }

    @Override
    public void onProgressUpdate(Void... progress) {
      draw();
    }

    @Override
    public RetrieveResult doInBackground(Void... params) {
      JSONArray jsonArray;

      long maxId = getDb().fetchMaxId();

      try {
        jsonArray = getApi().getTimelineSinceId(maxId);
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      } catch (AuthException e) {
        Log.i(TAG, &quot;Invalid authorization.&quot;);
        return RetrieveResult.AUTH_ERROR;
      } catch (ApiException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      }

      ArrayList&lt;Tweet&gt; tweets = new ArrayList&lt;Tweet&gt;();
      HashSet&lt;String&gt; imageUrls = new HashSet&lt;String&gt;();

      for (int i = 0; i &lt; jsonArray.length(); ++i) {
        if (isCancelled()) {
          return RetrieveResult.CANCELLED;
        }

        Tweet tweet;

        try {
          JSONObject jsonObject = jsonArray.getJSONObject(i);
          tweet = Tweet.create(jsonObject);
          tweets.add(tweet);
        } catch (JSONException e) {
          Log.e(TAG, e.getMessage(), e);
          return RetrieveResult.IO_ERROR;
        }

        imageUrls.add(tweet.profileImageUrl);

        if (isCancelled()) {
          return RetrieveResult.CANCELLED;
        }
      }

      getDb().addTweets(tweets, false);

      if (isCancelled()) {
        return RetrieveResult.CANCELLED;
      }

      publishProgress();

      for (String imageUrl : imageUrls) {
        if (!Utils.isEmpty(imageUrl)) {
          // Fetch image to cache.
          try {
            getImageManager().put(imageUrl);
          } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
          }
        }

        if (isCancelled()) {
          return RetrieveResult.CANCELLED;
        }
      }

      return RetrieveResult.OK;
    }

    @Override
    public void onPostExecute(RetrieveResult result) {
      if (result == RetrieveResult.AUTH_ERROR) {
        logout();
      } else if (result == RetrieveResult.OK) {
        SharedPreferences.Editor editor = mPreferences.edit();
        editor.putLong(Preferences.LAST_TWEET_REFRESH_KEY, Utils.getNowTime());
        editor.commit();
        draw();
        goTop();
      } else {
        // Do nothing.
      }

      updateProgress(&quot;&quot;);
    }
  }

  private class FollowersTask extends UserTask&lt;Void, Void, RetrieveResult&gt; {
    @Override
    public RetrieveResult doInBackground(Void... params) {
      try {
        ArrayList&lt;Long&gt; followers = getApi().getFollowersIds();
        getDb().syncFollowers(followers);
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      } catch (AuthException e) {
        Log.i(TAG, &quot;Invalid authorization.&quot;);
        return RetrieveResult.AUTH_ERROR;
      } catch (ApiException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      }

      return RetrieveResult.OK;
    }

    @Override
    public void onPostExecute(RetrieveResult result) {
      if (result == RetrieveResult.OK) {
        SharedPreferences.Editor editor = mPreferences.edit();
        editor.putLong(Preferences.LAST_FOLLOWERS_REFRESH_KEY, Utils
            .getNowTime());
        editor.commit();
      } else {
        // Do nothing.
      }
    }
  }

  // Menu.

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuItem item = menu.add(0, OPTIONS_MENU_ID_REFRESH, 0, R.string.refresh);
    item.setIcon(R.drawable.refresh);

    item = menu.add(0, OPTIONS_MENU_ID_DM, 0, R.string.dm);
    item.setIcon(android.R.drawable.ic_menu_send);

    /*
    item = menu.add(0, OPTIONS_MENU_ID_TOGGLE_REPLIES, 0,
        R.string.show_at_replies);
    item.setIcon(android.R.drawable.ic_menu_zoom);
    */

    return super.onCreateOptionsMenu(menu);
  }

  @Override
  public boolean onPrepareOptionsMenu(Menu menu) {
    /*
    MenuItem item = menu.findItem(OPTIONS_MENU_ID_TOGGLE_REPLIES);

    if (isReplies()) {
      item.setIcon(R.drawable.ic_menu_zoom_out);
      item.setTitle(R.string.show_all);
    } else {
      item.setIcon(android.R.drawable.ic_menu_zoom);
      item.setTitle(R.string.show_at_replies);
    }
    */

    return super.onPrepareOptionsMenu(menu);
  }

  public void toggleShowReplies() {
    mState = mState == STATE_REPLIES ? STATE_ALL : STATE_REPLIES;

    SharedPreferences.Editor editor = mPreferences.edit();
    editor.putInt(Preferences.TWITTER_ACTIVITY_STATE_KEY, mState);
    editor.commit();

    setupState();
  }

  private static final String INTENT_MODE = &quot;mode&quot;;
  private static final int MODE_REPLIES = 1;

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case OPTIONS_MENU_ID_REFRESH:
      doRetrieve();
      return true;
    case OPTIONS_MENU_ID_REPLIES:
      Intent repliesIntent = new Intent(this, TwitterActivity.class);
      repliesIntent.putExtra(INTENT_MODE, MODE_REPLIES);
      startActivity(repliesIntent);
      return true;
    case OPTIONS_MENU_ID_DM:
      launchActivity(DmActivity.createIntent());
      return true;
    case OPTIONS_MENU_ID_TOGGLE_REPLIES:
      toggleShowReplies();
      return true;
    }

    return super.onOptionsItemSelected(item);
  }

  // Various handlers.

  private View.OnKeyListener tweetEnterHandler = new View.OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
      if (keyCode == KeyEvent.KEYCODE_ENTER
          || keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
        if (event.getAction() == KeyEvent.ACTION_UP) {
          doSend();
        }
        return true;
      }
      return false;
    }
  };

	@Override
	public void onInit(int arg0) {
		ttsReady = true;
	}
}
</pre>
<p>Below is the Speak class which simply takes in a string of text and utilizing the Text-to-Speech synthesizes it.</p>
<pre class="brush: plain; title: ; notranslate">
package com.dart.android.twitter;

import com.google.tts.TTS;

public class Speak {

	public void speak(boolean ttsReady, TTS myTTS, String textToSpeak){
		if (ttsReady) {
			// This param does only work on pre-recorded voice and has no
			// effect on this speak.
			String[] params = { &quot;VOICE_FEMALE&quot; };
			// Speaks the text
			myTTS.speak(textToSpeak, 1, params);
		} 

		else {
			// Notifys the user if the TTS service is not ready or installed
//			Toast.makeText(this, &quot;TTS is not ready or  installed&quot;,
//					Toast.LENGTH_LONG).show();
		}
	}

	public void stop(boolean ttsReady, TTS myTTS){
		myTTS.stop();
	}

}
</pre>
<p>If you want to try the working copy you can download it by clicking the link below.</p>
<p><a href="/school_content/bin/TwitterActivity.apk"><img src="/images/download_now.png"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2009/10/10/talking-twitter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Powers of base 2 between 2 values using array in MIPS</title>
		<link>http://www.hdelossantos.com/2009/03/15/powers-of-base-2-between-2-values-using-array-in-mips/</link>
		<comments>http://www.hdelossantos.com/2009/03/15/powers-of-base-2-between-2-values-using-array-in-mips/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 04:46:11 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[code assignment]]></category>
		<category><![CDATA[hanly de los santos]]></category>
		<category><![CDATA[hdelossantos]]></category>
		<category><![CDATA[hdelossantos.com]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mips]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[register]]></category>
		<category><![CDATA[tv]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=349</guid>
		<description><![CDATA[Program requests and reads in exactly one character, which represents an exponent. If the value is acceptable, then the program reads in another value. The program calculates the base 2 power between the user input values, and then stores the calculated values in an array. It then prints the values in the array.]]></description>
			<content:encoded><![CDATA[<p>Program requests and reads in exactly one character, which represents an exponent. If the value is acceptable, then the program reads in another value. The program calculates the base 2 power between the user input values, and then stores the calculated values in an array. It then prints the values in the array.</p>
<p></p>
<pre class="brush: plain; title: ; notranslate">
# Assignment 3: Powers of 2 Assembly utilizing Array
# by Hanly De Los Santos
# Copyright ©2009, Hanly De Los Santos. All Rights Reserved.
# http://www.hdelossantos.com
#
# Program requests and reads in exactly one character,
# which represents an exponent. If the value is acceptable, then the
# program reads in another value. The program calculates
# the base 2 power between the user input values, and then
# stores the calculated values in an array. It then prints the
# values in the array.
#
		.text
		.globl __start 

# Load acceptable ascii decimal value for number ranges
# since input is read in as a character.
__start: 	li	$8, 48		# This is the decimal equivalent of 0
		li	$9, 57		# This is the decimal equivalent of 9

# Prompt the user for input.
		la	$11, prompt
		puts	$11

# Grab user input and store value in register 10
		getc	$10
		la	$11, newline	# Create new line
		lb	$17, ($11)
		putc	$17
		add	$15, $10, 0	# Make copy of contents of r10 in r15.
		sub	$15, $15, 48	# Convert char from first input to int.

# Test to determine whether or not the user input value is acceptable.
# If user input is less than 48 and greater than 57, branches to
# exit_donothing, where the user is told the input is wrong.
		bgt	$10, $9, exit_donothing
		blt	$10, $8, exit_donothing
		sub	$10, $10, 48	# After check, convert char to int.

# Prompt user for additional input
		la	$11, prompt2
		puts	$11

# Grab user input and store in r12
		getc	$12
		la	$11, newline	# Create new line
		lb	$17, ($11)
		putc	$17
		add	$18, $10, 0	# Make copy of contents of r12 in r18.
		sub	$18, $18, 48	# Convert char to int.

# Test to determine whether or not the user input value is acceptable.
# If user input is less than 48 and greater than 57, branches to
# exit_donothing, where the user is told the input is wrong.
		bgt	$12, $9, exit_donothing
		blt	$12, $8, exit_donothing
		sub	$12, $12, 48	# After check, convert char to int.

# Determine if the difference between the two user input values is 0
		bnez	$10, neqz
		beqz	$12, special_zero

# Determine difference between 2 values
neqz:		sub	$21, $12, $10	#Store diff of the two values in r21
		bltz	$21, exit_printgtr
		add	$21, $21, 1

# If the value was acceptable, proceed to calculate the power.
		li	$11, 2		# Load multiplier value into $11.
		li	$17, 2		# Initialize 17 to multiplier value

# Check to see if the second usr input is &gt; 1, if it is modify r10 so that
# the calculations can be made properly. This sets r10 = 2. If the second
# input is == 1, then print the results. Must also load 2 into 2nd array
# location here in case the seond input is 1.
		la	$16, powers
		li	$22, 1
		mult	$11, $22
		mflo	$11
		sw	$11, 4($16)
		li	$23, 1
		beq	$23, $12, print_result
		bgt	$10, $23, cont_gtn
		li	$10, 2

# Multiplication loop. While $10 != 0 keep multiplying $17 by 2, and
# decrement $10 by 1 every time this is done. Once $10 == 0, store
# the result.
cont_gtn:	sub	$10, $10, 1	# Since 2^1 has been taken care of
		add	$14, $10, 0
		add	$24, $10, 0
		add	$24, $24, 1

multiply_for:	mult	$17, $11	# Loop to determine the power val
		mflo	$17
		sub	$10, $10, 1
		bnez	$10, multiply_for

# The result is stored in the location of the user input * 4, which would
# give the matching address location on the array. This loops to
# multiply_for while the $10 is != $12.
nextval:	add	$10, $14, 0	# Restores r10 from copy
		mul	$14, $24, 4	# Calculation to determine the
		add	$23, $16, $14	#  location in which to place the
		sw	$17, ($23)	#  resulting power in the array.
		add	$10, $10, 1	# Increment the counters for next
		add	$24, $24, 1	#  iteration.
		add	$14, $10, 0
		li	$17, 2		# restore the multiplier value
		blt	$10, $12, multiply_for
		beq	$10, $12, print_result

# Display the value of the exponential function. This loops through the
# values in the array starting at the first user input until the
# difference between the first and last user input is 0.
print_result:	la	$14, str3
		puts	$14		# Print out &quot;2^&quot;
		li	$v0, 1
		move	$a0, $15
		syscall			# Print out value of user input.
		la	$16, str4
		puts	$16		# Print out '='
		li	$v0, 1
		la	$20, powers	# Calculation to determine the
		mul	$19, $15, 4	#  location of the power value.
		add	$23, $20, $19
		lw	$17, ($23)
		move	$a0, $17
		syscall			# Print out result.
		la	$13, newline	# Create new line
		lb	$12, ($13)
		putc	$12
		sub	$21, $21, 1
		add	$15, $15, 1
		bnez	$21, print_result
		b	endofline

# Print out the result for 2 to the power of 0 if teh two user
# inputs are 0 (special case).
special_zero:	la	$14, str3
		puts	$14		# Print out &quot;2^&quot;
		li	$v0, 1
		move	$a0, $15
		syscall			# Print out value of user input.
		la	$16, str4
		puts	$16		# Print out '='
		li	$v0, 1
		la	$20, powers
		lw	$17, ($20)	# Print first value of array.
		move	$a0, $17
		syscall
		la	$13, newline	# Create new line
		lb	$12, ($13)
		putc	$12
		b	endofline

# If second input is less than or not equal to first input, print mbgtrthan.
exit_printgtr:	la	$13, mbgtrthan
		puts	$13

# If the input is not appropriate, print str2 and exit.
exit_donothing:	la	$13, str2
		puts	$13
		b	endofline

# This is the exit statement.
endofline:	done		# END OF PROGRAM

# Define strings which will be used throughout program
		.data
prompt:		.asciiz &quot;Enter a digit '0'-'9': &quot;
prompt2:	.asciiz &quot;Enter another digit '0'-'9': &quot;
mbgtrthan:	.asciiz &quot;Second digit must be greater than or equal to the first digit.\n&quot;
str2:		.asciiz &quot;Bad user input.  Quitting.\n&quot;
str3:		.asciiz &quot;2^&quot;
str4:		.asciiz &quot; = &quot;
newline:  	.byte  '\n'
		.align 4
powers:		.word	1:10		# Create a 10-element int array.
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2009/03/15/powers-of-base-2-between-2-values-using-array-in-mips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powers of base 2 in MIPS</title>
		<link>http://www.hdelossantos.com/2009/03/01/powers-of-base-2-in-mips/</link>
		<comments>http://www.hdelossantos.com/2009/03/01/powers-of-base-2-in-mips/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 04:36:25 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[code assignment]]></category>
		<category><![CDATA[hanly de los santos]]></category>
		<category><![CDATA[hdelossantos]]></category>
		<category><![CDATA[hdelossantos.com]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mips]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[register]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=341</guid>
		<description><![CDATA[Program requests and reads in exactly one character, which represents an exponent. The program calculates the base 2 power, and then prints the calculated value.]]></description>
			<content:encoded><![CDATA[<p>Program requests and reads in exactly one character, which represents an exponent. The program calculates the base 2 power, and then prints the calculated value.</p>
<p></p>
<pre class="brush: plain; title: ; notranslate">
# Assignment 2: Powers of 2 Assembly
# by Hanly De Los Santos
# Copyright ©2009, Hanly De Los Santos. All Rights Reserved.
# http://www.hdelossantos.com
#
# Program requests and reads in exactly one character,
# which represents an exponent. The program calculates
# the base 2 power, and then prints the calculated value.
#
		.text
		.globl __start 

# Load acceptable ascii decimal value for number ranges
# since input is read in as a character.
__start: 	li	$8, 48		# This is the decimal equivalent of 0
		li	$9, 57		# This is the decimal equivalent of 9

# Prompt the user for input.
		la	$11, prompt
		puts	$11

# Grab user input and store value in register 10
		getc	$10
		la	$11, newline	# Create new line
		lb	$17, ($11)
		putc	$17
		add	$15, $10, 0	# Make copy of contents of r10 in r15.
		sub	$15, $15, 48	# Convert char to int.

# Test to determine whether or not the user input value is acceptable.
# If user input is less than 48 and greater than 57, branches to
# exit_donothing, where the user is told the input is wrong.
		bgt	$10, $9, exit_donothing
		blt	$10, $8, exit_donothing
		sub	$10, $10, 48	# After check, convert char to int.

# If the value was acceptable, proceed to calculate the power.
# Checks to determine if $10 is 0 or 1 since they are special cases.
# If value is 0 or 1, branches to their respective prints.
		li	$11, 2		# Load multiplier value into $11.
		beqz	$10, result_zero
		li	$17, 1
		beq	$10, $17, result1
		li	$17, 2		# Initialize 17 to multiplier value
		sub	$10, $10, 1	# Since 2^1 has been taken care of

# Multiplication loop. While $10 != 0 keep multiplying $17 by 2, and
# decrement $10 by 1 every time this is done. Once $10 == 0, print_result.
multiply_for:	mult	$17, $11
		mflo	$17
		sub	$10, $10, 1
		bnez	$10, multiply_for
		beqz	$10, print_result

# Display the value of the exponential function.
print_result:	la	$14, str3
		puts	$14		# Print out &quot;2^&quot;
		li	$v0, 1
		move	$a0, $15
		syscall			# Print out value of user input.
		la	$16, str4
		puts	$16		# Print out '='
		li	$v0, 1
		move	$a0, $17
		syscall			# Print out result.
		la	$13, newline	# Create new line
		lb	$12, ($13)
		putc	$12
		b	endofline

# Print out the result for 2 to the power of 0 (special case).
result_zero:	la	$14, str3
		puts	$14		# Print out &quot;2^&quot;
		li	$v0, 1
		move	$a0, $15
		syscall			# Print out value of user input.
		la	$16, str4
		puts	$16		# Print out '='
		li	$v0, 1
		li	$a0, 1
		syscall
		la	$13, newline	# Create new line
		lb	$12, ($13)
		putc	$12
		b	endofline

# Print the result for 2 to the power of 1 (special case).
result1:	la	$14, str3
		puts	$14		# Print out &quot;2^&quot;
		li	$v0, 1
		move	$a0, $15
		syscall			# Print out value of user input.
		la	$16, str4
		puts	$16		# Print out '='
		li	$v0, 1
		li	$a0, 2
		syscall
		la	$13, newline	# Create new line
		lb	$12, ($13)
		putc	$12
		b	endofline

# If the input is not appropriate, print str2 and exit.
exit_donothing:	la	$13, str2
		puts	$13
		b	endofline

# This is the exit statement.
endofline:	done		# END OF PROGRAM

# Define strings which will be used throughout program
		.data
prompt:		.asciiz &quot;Enter a digit '0'-'9': &quot;
str2:		.asciiz &quot;Bad user input.  Quitting.\n&quot;
str3:		.asciiz &quot;2^&quot;
str4:		.asciiz &quot; = &quot;
newline:  	.byte  '\n'
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2009/03/01/powers-of-base-2-in-mips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powers of base 2 in C</title>
		<link>http://www.hdelossantos.com/2009/02/21/powers-of-base-2-in-c/</link>
		<comments>http://www.hdelossantos.com/2009/02/21/powers-of-base-2-in-c/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 04:26:33 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[c language]]></category>
		<category><![CDATA[code assignment]]></category>
		<category><![CDATA[hanly de los santos]]></category>
		<category><![CDATA[hdelossantos]]></category>
		<category><![CDATA[hdelossantos.com]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mips]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tea]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=334</guid>
		<description><![CDATA[This program takes a user input from 1 through 512 (inclusive), and calculates all powers of two that are less than or equal to the value. The program prints out all of these values. NOTE: Due to my usage of the math library&#8217;s log function, it is necessary to compile using -lm under Unix systems [...]]]></description>
			<content:encoded><![CDATA[<p>This program takes a user input from 1 through 512 (inclusive), and calculates all powers of two that are less than or equal to the value. The program prints out all of these values. </p>
<p><span style="color: #ff0000;">NOTE: Due to my usage of the math library&#8217;s log function, it is necessary to compile using -lm under Unix systems for the linker to properly define the log function. Information referenced from: <a href="http://c-faq.com/fp/libm.html">http://c-faq.com/fp/libm.html</a></span></p>
<p></p>
<pre class="brush: cpp; title: ; notranslate">
/* Assignment1: Powers of 2
 * by Hanly De Los Santos
 * Copyright ©2009, Hanly De Los Santos. All Rights Reserved.
 * http://www.hdelossantos.com
 *
 * This program takes a user input from 1
 * through 512 (inclusive), and calculates all powers of
 * two that are less than or equal to the value. The
 * program prints out all of these values.
 *
 * NOTE: Due to my usage of the math library's log function,
 * it is necessary to compile using -lm under Unix systems
 * for the linker to properly define the log function.
 * Information referenced from: http://c-faq.com/fp/libm.html
 */

/* Load standard I/O library */
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;math.h&amp;gt;

/* Define macro */
#define ARRAYSIZE 10

/* Declare function prototypes to define the output of the
 * following functions.
 */
void printPowers(int ar[], int firstindex, int lastindex);
void setPowers(int userinteger, int ar[], int lastindex);

main(int argc, char *argv[]){
	int powers[ARRAYSIZE];

	/* This determines whether there are 2 arguments in the command
	 * line input. If there are less than 2 arguments, then a message
	 * is printed prompting the user to enter a positive integer value.
	 */
	if( argc &amp;lt; 2)
		printf(&amp;quot;Invalid command line. Positive integer value required.\n&amp;quot;);

	/* If there are 2 variables, then the second variable is tested
	 * for the required integer values.
	 */
	else{
		int usrval = atoi(argv[1]);

		/* If the user input value is within the accepted range
		 * 1-512, then the operation is done with the user value.
		 */
		if( usrval &amp;gt;= 1 &amp;amp;&amp;amp; usrval &amp;lt;= 512 ){
			int maxexp = ((log(usrval))/log(2));
			setPowers( usrval, powers, maxexp);
			printf(&amp;quot;Powers of 2 that are less than or equal to %d are:\n&amp;quot;, usrval);
			printPowers(powers, 0, maxexp);
		}

		/* If the value is greater than 512, the operation is done with the
		 * maximum value of 512
		 */
		else if ( usrval &amp;gt; 512 ){
			printf(&amp;quot;Powers of 2 that are less than or equal to 512 are:\n&amp;quot;, usrval);
			setPowers( 512, powers, 9);
			printPowers(powers, 0, 9);
			printf(&amp;quot;argc is equal to: %d&amp;quot;, argc);
		}

		/* If a character/negative number is entered instead of an integer, the user is
		 * prompted that a positive integer is required to complete the
		 * operation.
		 */
		else if ( !isdigit(usrval) || usrval &amp;lt;= 0 ){
			printf(&amp;quot;Invalid command line. Positive integer value required.\n&amp;quot;);
			printf(&amp;quot;argc is equal to: %d&amp;quot;, argc);
		}
	}

	return 0;
}

/* This function sets the array's values; only the array elements
 * whose values are less than or equal to the userinteger are set.
 * It calls function power() for each value.
 */
void setPowers(int userinteger, int ar[], int lastindex){
	int i;
	for( i = 0; i &amp;lt;= lastindex; i++)
		ar[i] = power( 2, i );
}

/*This function calculates and returns baseexponent utilizing the
 * math library function 'pow'.
 */
int power(int base, int exponent){
	int e;

	e = pow(base, exponent);
	return e;
}

/* This function prints the program's output. For each array
 * element in the range of integers defined by firstindex and
 * lastindex, the function prints one line of the output.
 */
void printPowers(int ar[], int firstindex, int lastindex){
	int p;
	for( p = 0; p &amp;lt;= lastindex; p++)
		printf(&amp;quot;2^%d = %d\n&amp;quot;, p, ar[p] );
}
</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2009/02/21/powers-of-base-2-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.112 seconds -->

