On the Go

Going Mobile with SMS

One way that we can help with the audience problem is to utilize something like SMS (or perhaps email) to alert people of an event or even alert us when people are available and ready to participate in a live fashion.

TextMarks is a free online service that allows for the sending and recieving of text messages on the regular mobile network. TextMarks allows anyone to register a keyword of their choosing and to utilize the shortcode 41411.

(I registered the liveweb for demonstration purposes)

One of the great things about TextMarks is that you can have the service hit a script running on a remote server through a web request (HTTP).

Using this functionality as well as the ability to send SMS back you can allow mobile users to participate in "Live Web" applications.

To have my keyword hit a script that I am running on a webserver, I have to choose "Respond to a keyword with text from a webpage" when setting up the keyword with TextMarks:



The URL I put in is as follows: http://itp.nyu.edu/~sve204/liveweb/textmarks.php?phone=\p&text=\0

TextMarks substitutes the user's phone number where the "\p" is and the message they send where the "\0" is. (More documentation can be found here: http://www.textmarks.com/dev/docs/recv/.

Now I can write the "textmarks.php" script..
<?
        // This PHP file: textmarks.php gets hit with phone and message when someone texts 41411 liveweb
        // http://itp.nyu.edu/~sve204/liveweb/textmarks.php?phone=\p&text=\0 

        // Phone Number:
        $phone = $_GET['phone'];

        // Message:
        $message = $_GET['text'];

        // Save the message to the text file which changes my pages
        $fp=fopen('/home/sve204/public_html/liveweb/textmarks.txt','w');
        fwrite($fp,$message);
        fclose($fp);

        echo "Yay!!!  Thanks";
?>
		
Now when ever someone texts 41411 with the keyword liveweb this script is called and they get a text back that says: "Yay!! Thanks"

In addition this script writes out the contents of their message to a text file: "textmarks.txt" on the server (this file needs to exist in the first place).

SMS + AJAX

Now we can do a lot of different things with their message using AJAX or Flash. This example AJAX based page, takes the contents of their message and changes the background color of the page:

<html>
	<head>
		<!-- Always load up the ajax.js file so you don't have to do all of the hard work -->
		<script type="text/javascript" src="ajax.js"></script>
		
		<!-- Do your own JavaScript below -->
		<script type="text/javascript">

			// A variable to hold the interval id
			var interval = null;	
	
			// A function to call our server side file or script
			// This get's triggered by the interval (in function setup_ajax()
			function call_ajax()
			{
				makeHttpRequest('http://itp.nyu.edu/~sve204/liveweb/textmarks.txt',ajax_return);
			}

			// A function that gets called when the server responds
			// This is where you would do what you want with the response
			// In this case, I am changing the color of the page
			function ajax_return(response)
			{
				document.bgColor="#" + response;
			}
	
			// Setup AJAX function, creates a timeout so that we run something periodically
			function setup_ajax()
			{
				// Set interval of 2000 milliseconds
				// Keeps going over and over again
				interval = setInterval("call_ajax()",2000);
			}			
		
			// Register setup_ajax with the onload event of the window (when it is done loading)..	
			// This makes setup_ajax run after the browser renders the page
			function addOnLoad()
			{
				if (window.addEventListener)
				{
					window.addEventListener('load', setup_ajax, false);
				}
				else if (window.attachEvent)
				{
					window.attachEvent('onload', setup_ajax);
				}
			}
			// Tell the browser to run the addOnLoad function above
			addOnLoad();
		</script>
	</head>
	<body>
		<h1>Nothing Really On This Page</h1>
	</body>
</html>
		
As you can see, the AJAX is periodically checking the text file that the textmarks script is writing to and changing the color of the page. You can try it: http://itp.nyu.edu/~sve204/liveweb_fall2009/textmarks_example.php

Of course, you can do so much more.. Have people participate in a chat through text and online or have people be able to alter a page that is displayed on a large screen or anything along those lines..

Here is another example which uses the keyword "tunnel" and just displays whatever you type in: http://itp.nyu.edu/~sve204/tunnel_d.html

AJAX Gotchas

One thing that you need to be concerned with when doing any type of AJAX is that the request through AJAX needs to come from the same server that page initially loaded from. In our case, itp.nyu.edu.. You can't load data from elsewhere without getting it from itp.nyu.edu in the end. Of course, you could have a PHP script make the request for data from elsewhere and return that data to the AJAX script.

SMS + Flash

We can also use this technique to do very similar things in Flash.

This AS3 file (called Flajax.as) loads data from the textfile as does the AJAX script below. Instead of changing the background color of the entire page, it just changes the background color of itself and write the data to a textfield.

package com.mobvcasting
{
	import flash.display.Sprite;
	import flash.text.TextField;
	
	// Network library
	import flash.net.*;
	
	// Events library
	import flash.events.*;
	
	// Timer library
	import flash.utils.Timer;
	
	
	public class Flajax extends Sprite
	{
		// Declare a String variable
		private var astring:String = "Hello World";
		
		// Declare a Text Field		
		private var displayText:TextField = new TextField();
		
		// Declare the URL Loader
		private var loader:URLLoader;
		
		// Declare the request
		private var request:URLRequest;
		
		public function Flajax():void
		{
			// Set the text of the textfield to be our string
			displayText.text = "" + astring;
			
			// Display it
			addChild(displayText);
			this.scaleX = 1;
			this.scaleY = 1;
	
			this.width = 100;
			this.height = 100;
			
			this.x = 20;
			this.y = 40;
	
			this.opaqueBackground = 0xFF0000;
			
			// Create the URL Loader - Load any Web document, like you would with AJAX
			loader = new URLLoader();
	
			// Register the function that will receive the content
			loader.addEventListener(Event.COMPLETE, pageLoaded);
	
			// Create the request
			request = new URLRequest("http://itp.nyu.edu/~sve204/liveweb/textmarks.txt");
	
			// Setup the Timer
			var myTimer:Timer = new Timer(2000, 0);
			myTimer.addEventListener("timer", loadPage);
			myTimer.start();			
			
			// Make the request
			//loadPage();
			// Called by the timer
		
		}
		
		private function loadPage(event:TimerEvent):void
		{
			// Make the request
			try {
				loader.load(request);
			} catch (error:Error) {
				trace("Unable to load requested document.");
			}		
			trace("Should have loaded");
		}
		
		public function pageLoaded(event:Event):void
		{
			trace("loaded: " + loader.data);            
			displayText.text = loader.data;
			
			if (loader.data.valueOf() == "blue")
			{
				// have to use "valueOf" to do == comparison
				this.opaqueBackground = "0x0000FF";
				trace("should be blue");
				trace(this.opaqueBackground)
			}
			else if (loader.data.valueOf() == "red")
			{
				// have to use "valueOf" to do == comparison
				this.opaqueBackground = "0xFF0000";       
				trace("should be red");
				trace(this.opaqueBackground);
			}
			else 
			{
				this.opaqueBackground = "0x" + loader.data;       
				trace("should be: " + loader.data);
				trace(this.opaqueBackground);
			}
		}
	}
}
You can try it out: http://itp.nyu.edu/~sve204/liveweb/Flajax.swf

Download it: http://itp.nyu.edu/~sve204/liveweb/Flajax.as

The keys to making this work are the following chunks of code:

This allows us to connect to network.
// Network library
import flash.net.*;

This allows us to get notified when something happens.
    
// Events library
import flash.events.*;

This allows us to do something periodically.
// Timer library
import flash.utils.Timer;

The following code in the constructor sets up the objects that are going to do the work. We need a URLLoader, an event listener for the URLLoader and a timer to periodically call our "loadPage" function.
// Create the URL Loader - Load any Web document, like you would with AJAX
loader = new URLLoader();

// Register the function that will receive the content
loader.addEventListener(Event.COMPLETE, pageLoaded);

// Create the request
request = new URLRequest("http://itp.nyu.edu/~sve204/liveweb/textmarks.txt");

// Setup the Timer
var myTimer:Timer = new Timer(2000, 0);
myTimer.addEventListener("timer", loadPage);
myTimer.start();			

// Make the request
//loadPage();
// Called by the timer

The laodPage function below actually makes the request (just like an ajax request) to the server for the text file:
private function loadPage(event:TimerEvent):void
{
	// Make the request
	try {
		loader.load(request);
	} catch (error:Error) {
		trace("Unable to load requested document.");
	}		
	trace("Should have loaded");
}

The "pageLoaded" function is what gets called when the page is loaded. It is the response from the text file or script that is called above. In this case, it takes the contents and changes the background color.
public function pageLoaded(event:Event):void
{
	trace("loaded: " + loader.data);            
	displayText.text = loader.data;
	
	if (loader.data.valueOf() == "blue")
	{
		// have to use "valueOf" to do == comparison
		this.opaqueBackground = "0x0000FF";
		trace("should be blue");
		trace(this.opaqueBackground)
	}
	else if (loader.data.valueOf() == "red")
	{
		// have to use "valueOf" to do == comparison
		this.opaqueBackground = "0xFF0000";       
		trace("should be red");
		trace(this.opaqueBackground);
	}
	else 
	{
		this.opaqueBackground = "0x" + loader.data;       
		trace("should be: " + loader.data);
		trace(this.opaqueBackground);
	}
}

(You could also use Flash Remoting: http://www.adobe.com/products/flashremoting/ or open source clones: http://osflash.org/open_source_flash_projects#servers_and_remoting (AMFPHP, openAMF, AMF::Perl and so on)

Flash Gotchas

As with AJAX their are some gotcha's with this script as well. It needs to either be on the same server as the SWF or a "crossdomain.xml" file has to be put on the server you are requesting data from. It also can't be run locally, it needs to come from the server.

Send SMS

Another great thing that can be done with TextMarks is to send an SMS to an individual. (First the individual needs to subscribe to your keyword).

You could use this to alert people when you are "live" or you could use it to alert you to the fact that someone is visiting your "live" page.

In order to do this, you need to register for an API key from TextMarks (it takes some time so do it early): http://www.textmarks.com/dev/api/reg/?ref=devsb

TextMarks, being the nice folks that they are have written a PHP library that uses their API, making things like sending messages very easy.

Documentation is here: http://www.textmarks.com/dev/docs/apiclient/php/

Their PHP library is here: http://www.textmarks.com/dev/docs/apiclient/php/TextMarksAPIClient.class.php Here is an example PHP script which uses their library and API: (PHP Page: sendmesomething.php)
<?php
// Require/Import the TextMarksAPIClient.class.php file
// Download from: http://www.textmarks.com/dev/docs/apiclient/php/TextMarksAPIClient.class.php
require "TextMarksAPIClient.class.php";

ini_set('display_errors', true);
ini_set('display_startup_errors', true);
error_reporting(E_ALL);

// This page get's called by AJAX when someone is on a page for a while (2 minutes)...
// Now I know I have audience and I can go online and interact with them..
// I should probably check the user agent to make sure it is a real person and not Google or Yahoo but they shouldn't run JavaScript anyway..
sendTextToMe();

// Send a text message to a single TextMark subscriber:
function sendTextToMe()
{
	
	// TextMarks API Key: Request from: http://www.textmarks.com/dev/api/reg/?ref=devapi
	$sMyApiKey='MYAPIKEY';
	
	// TextMarks Username or Phone Number
	$sMyTextMarksUser = 'MYPHONENUMBER'; //(or my TextMarks phone)
	$sMyTextMarksPass = 'MYPASSWORD';
	
	// TextMarks Keyword
	$sKeyword = 'MYKEYWORD';
	
	// Who are you going to send the text to?
	$sTo = 'MYPHONENUMBER';
	
	// The message to send
	$sMessage = "Someone is on your site";
	
	// Create the TextMarks Object with the above parameters
	$tmapi = new TextMarksAPIClient_Messaging($sMyApiKey, $sMyTextMarksUser, $sMyTextMarksPass);
	
	// Send the message!
	$tmapi->sendText($sKeyword, $sTo, $sMessage);
	
	// For debugging, dump out the results
	var_dump($tmapi);
	
	echo "Notified";
}
?>
If you visit this page in a browser, it will trigger a message. This could easily be placed in a normal web page to alert you that someone is viewing your page. Unfortunately, you would be getting text messages every time someone or something (google bot, msn bot and the like) loads your page.

Going one step further would be to trigger it via AJAX after a certain amount of time so you know that someone is sticking around and they can run javascript/ajax (unlike a google crawler or yahoo crawler)

Here is Live Page which triggers the above through AJAX after 20 seconds. I then know that someone is there and I can go LIVE: (It is almost identical to the color changing example above but instead of reading from the text file it calls the above PHP script and instead of happening over and over again, it happens once (setTimeout instead of setInterval.) Of course it also has a Flash video player so that the user can see me should I decide to go live..)
<html>
	<head>
		<!-- Always load up the ajax.js file so you don't have to do all of the hard work -->
		<script type="text/javascript" src="ajax.js"></script>
		
		<!-- Do your own JavaScript below -->
		<script type="text/javascript">

			// A variable to hold the interval id
			var interval = null;	
	
			// A function to call our server side file or script
			// This get's triggered by the interval (in function setup_ajax()
			function call_ajax()
			{
				makeHttpRequest('http://itp.nyu.edu/~sve204/liveweb/sendmetext.php',ajax_return);
			}

			// A function that gets called when the server responds
			// This is where you would do what you want with the response
			// In this case, I am changing the color of the page
			function ajax_return(response)
			{
				alert(response);
			}
	
			// Setup AJAX function, creates a timeout so that we run something periodically
			function setup_ajax()
			{
				// Set interval of 20000 milliseconds = 20 seconds
				// Keeps going over and over again - Nope, using setTimeout so it only happens once
				interval = setTimeout("call_ajax()",20000);
			}			
		
			// Register setup_ajax with the onload event of the window (when it is done loading)..	
			// This makes setup_ajax run after the browser renders the page
			function addOnLoad()
			{
				if (window.addEventListener)
				{
					window.addEventListener('load', setup_ajax, false);
				}
				else if (window.attachEvent)
				{
					window.attachEvent('onload', setup_ajax);
				}
			}
			// Tell the browser to run the addOnLoad function above
			addOnLoad();
		</script>
	</head>
	<body>
		<h1>If you hang out here..  I will get notified and I might come online</h1>
		
    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="550" height="400" id="player_stream" align="middle">
        <param name="allowScriptAccess" value="sameDomain" />
        <param name="movie" value="new_player_stream.swf" />        
		<param name="quality" value="high" />        
		<param name="bgcolor" value="#ffffff" />       
		<param name="flashvars" value="rtmp_url=rtmp://itp-flash.es.its.nyu.edu/sve204/live&thestream=gottext" />   
	<embed src="new_player_stream.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="player_stream" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="rtmp_url=rtmp://itp-flash.es.its.nyu.edu/sve204/live&thestream=gottext" />
     </object>		
		
	</body>
</html>
If you are really curious if I will respond, visit the page: My Live Home Page

Live Video Streaming from the phone

Several services exist which offer an application that you can run on a mobile phone to stream live video from the phone to the internet.

Flixwagon - Nokia, iPhone (jailbroken)
Livecast - Too many to list (not including iPhone)
Qik - Many (including Android and iPhone - iTunes Store)
UStream - Nokia and Android
Bambuser - Android, S60 (Nokia, Sony Ericsson, etc..), iPhone (jailbroken?) and Windows Mobile

Most of these services allow you to use location from your device as well as allow you to embed the stream into your own page (embed code).

Here is my live Qik feed:



One interesting thing about Qik is that their embed code is based around an RSS feed of the actual FLV files. This should allow a flash player to be developed with media that is almost live..

Live Web from Phone Call

Asterisk, the open source PBX system can be used to drive web pages through AJAX or Flash via a phone call.

Using Asterisk's AGI capabilities, a script can be executed which logs touchtone data from a call:
#!/usr/local/bin/php -q
<?PHP
require('/var/lib/asterisk/agi-bin/phpagi.php');

$agi = new AGI();

$agi->stream_file("vm-extension");
$return = $agi->wait_for_digit(10000);
while ($return['result'] > 0)
{
        $ascii = chr($return['result']);
        $agi->say_number($ascii);
        file_put_contents("/home/NETID/public_html/webservice/data.txt",time() . "," . $agi->request["agi_uniqueid"] . "," . $agi->request["agi_callerid"] . "," . $ascii . "\n",FILE_APPEND);
        $return = $agi->wait_for_digit(100000);
}
?>
(Of course, make sure the path to PHP is correct as is the path to save the data.txt file.)

From the web server side, another script can be written which serves that data to an application in AJAX or Flash.
<?
	// The client will send a timestamp if it want's new stuff from the timestamp
	$timestamp = 0;
	if (isset($_GET['ts']))
	{
		$timestamp = $_GET['ts'];
	}

	$data = file_get_contents("data.txt");
	$dataarray = explode("\n",$data);
	if ($timestamp > 0)
	{
		// Send everything from the timestamp forward
		for ($i = sizeof($dataarray) - 10; $i < sizeof($dataarray); $i++)
		{
			$currentline = explode(",",$dataarray[$i]);
			if (sizeof($currentline) > 0)
			{
				if ($currentline[0] > $timestamp)
				{
					echo($dataarray[$i]."\n");
				}
			}
		}
	}
	else
	{
		// Just send the last one
		if (sizeof($dataarray) > 1)
		{
			echo($dataarray[sizeof($dataarray)-2]);
		}
	}
?>
Using that, we can write something in AJAX which gets the data from the phone call and do something with it.

This example just displays the calls since the page was loaded and the touchtone keys that are pressed: AJAXified Phone Call

Live Audio Streaming from the phone

A phone, being that it is a phone is a good platform for transmitting voice. Using a system such as Asterisk and a bit of programming, a normal phone call can be turned into a live audio stream.

This is a file called runEAGIStreamer.sh which launches a Java application which reads the audio from Asterisk and sends it off to icecast for streaming to the internet..
		#!/bin/sh
		/usr/java/jdk1.5.0_09/bin/java -classpath /home/sve204/agi_examples/ JEAGIStreamer $$
		


Here is the the asterisk dialplan which runs the above shell script:
		[sve204_eagistream]
		exten => s,1,EAGI(/home/sve204/asterisk_agi/runEAGIStreamer.sh);
		exten => s,n,Goto(redial_sve204,s,1);
		
Finally, here is the code of the Java application JEAGIStreamer.java

To compile this you need to at least enter the appropriate server, password and mount point for the Icecast compatible streaming server

Following that, the command to compile on Social is: /usr/java/jdk1.5.0_09/bin/javac JEAGIStreamer.java

To listen to anyone calling my script you would put the following URL into iTunes/WinAMP/Real or pretty much anything else: http://asterisk.itp.tsoa.nyu.edu:8000/asterisk