Friday 29 January 2010

Hero Code

After creating my program, I encountered some small problems regarding refreshing web feeds. I posted the problem & my code on the Processing forum & one of the other members made me a completely new program that works better than I could ever imagine! After tinkering with the code to work seamlessly with Arduino, I have got my finished code:

import processing.video.*; // import theProcessing video library
import processing.serial.*; // import the Processing serial library

static final boolean USE_ARDUINO = true;

static final boolean USE_WEBCAM = false;
static final String WEBCAM_STRING = "USB PC Camera-WDM";

static final int MAX_LOAD_ATTEMPTS = 15; // Number of times to try loading a web image

static final String[] feedSetup = new String[] {
"Adelaide Market Observer", "http://www.adelaidecitycouncil.com/netcatapps/webcam/images/centralMkt.jpg", // Adelaide Market
"Vancouver Observer", "http://www.cbc.ca/bc/webcam/images/webcam.jpg", // Vancouver Building Site
"Adelaide Lantern Observer", "http://www.adelaidecitycouncil.com/netcatapps/webcam/images/rundleEast.jpg", // Rundle Mall East & Lantern
"Colony Observer", "http://www.draperbee.com/webcam/pic/image.jpg?1262444320177", // Beehive
"Adelaide 3 Observer", "http://www.adelaidecitycouncil.com/NetcatApps/webcam/images/bellsth.jpg", // Adelaide Bell Street South
"Aruba Observer", "http://www.bucuticam.com/arubacam.jpg", //Aruba, Netherlands Antilles
"Turtle Dome Observer", "http://www.yosemite.org/DSN/wwwyosemiteassociationorg/Content/Webcam/turtleback.jpg", //Yosemite, Turtle Dome
"Brooklyn Bridge Observer", "http://brooklyn-bridge.mobotixcam.de/record/current.jpg?rand=380424", //Brooklyn Bridge
"Bass Rock Observer", "http://www.outercam.co.uk/ssc/camera3.jpg?1260446915311", // Bass Rock, North Berwick
"Bar Observer", "http://ecoast.vs.oiccam.com:443/ftp/capcom/jackalope/image.jpg?rand=14:52:10", //Jackalope Jacks Bar, North Carolina
"Panama Canal Observer", "http://webcams.pancanal.com/webcam/miraflores.jpg", // Panama Canal
"Dundee Satellite Observer", "http://www.sat.dundee.ac.uk/webcam/cam0.jpg", //Dundee Tower Building
"Living Room Observer", "http://www.xs4all.nl/~twocats/cam/Cam-A.jpg", //Amsterdam House
"Ablerta University Observer", "http://www.cs.ualberta.ca/~lake/cam/jpg/large/201.jpg", //Alberta University
"Drama Observer", "http://facweb.furman.edu/~rbryson/dramadept/TheatreCamPic.jpg", //Student Theatre
};

Serial Arduino; // The serial port

//boolean onoff = true; // Display the local webcam?

PFont font; // Description text font

// Feeds, current feed index and reference for current feed (from the ArrayList)
private ArrayList feeds;
int feedIndex; // Current feed index
int camIndex = -1; // Index of cam (if available)
Feed currentFeed;

float xpos, ypos, onoff; // Starting position of the webcam feed
float specialWidth = 1450.0;

float scrollOffset = 0; // Text scrolling offset
float scrollSpeed = 3; // Text scrolling speed

int scrolltext;

long clock; // Realtime clock in milliseconds, based on millis(), updated in ticktock()

void setup()
{
ticktock();

size(1050,760,P3D);

font = loadFont("Consolas-36.vlw");
textFont(font, 36);

if (USE_ARDUINO && !online)
{
// List all the available serial ports
println(Serial.list());

Arduino = new Serial(this, Serial.list()[1], 9600);

// read bytes into a buffer until you get a linefeed (ASCII 10):
Arduino.bufferUntil('\n');
}

feeds = new ArrayList();

if (USE_WEBCAM && !online) try
{
// List all the available cameras
println(Capture.list());
CaptureFeed captureFeed = new CaptureFeed(this, "Camera One", WEBCAM_STRING, width/2, height/2, 30);
camIndex = feeds.size();
feeds.add(captureFeed);
}
catch (Exception e)
{
println("Error initialising webcam (" + WEBCAM_STRING + "): " + e.getMessage());
}

// Set up web feeds
for (int i = 0; i <>
{
Feed feed = new WebFeed(feedSetup[i], feedSetup[i+1]);
feeds.add(feed);
}

selectFeed(0); // Maybe webcam
}

void draw()
{
ticktock();

background(0);
rotate(-PI/2);

scrollOffset += scrollSpeed;
if (scrollOffset > width + specialWidth)
{
scrollOffset = 0;
}

currentFeed.update();
currentFeed.display();

if(onoff == 0){
background(0);
}
}

public void ticktock()
{
clock = millis();
}

void serialEvent(Serial Arduino)
{
// Read the serial buffer:
String myString = Arduino.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null){

myString = trim(myString);

// split the string at the commas
// and convert the sections into integers:
int sensor[] = int(split(myString, ','));

// print out the values you got:
for (int sensorNum = 0; sensorNum <>
print("sensor " + sensorNum + ": " + sensor[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensor.length > 1){
xpos = map(sensor[0], 0, 1023, -width/2, -(width/4)*3);
ypos = map(sensor[1], 0, 1023, 0, (height- 150 - height/2));
int feedSelection = constrain((int)map(sensor[2], 0, 1023, 0, feeds.size() - 1), 0, feeds.size() - 1);
selectFeed(feedSelection);
onoff = map(sensor[3], 0, 1, 0, 1);

if (onoff == 1)
{
selectFeed(camIndex);
}

scrolltext = (int)map(sensor[4], 0, 1023, 0, currentFeed.description.length() - 1);
}
}
}


void displayScrollText(String displayText)
{
text(displayText, width - scrollOffset, height + 200);
}

public void selectFeed(int feedSelection)
{
if (feedSelection <>= feeds.size())
{
println("Cannot select feedIndex " + feedSelection);
return;
}

feedIndex = feedSelection;
currentFeed = (Feed)feeds.get(feedIndex);
}

//============================================================

/**
* Feed class
* Contains feed metadata (description and locator) and
* proscription for update() and display() methods in subclasses
*/

abstract class Feed
{
public String description;
public String locator;

public Feed(String description, String locator)
{
this.description = description;
this.locator = locator;
}

public abstract void update(); // Must be implemented in subclasses
public abstract void display(); // Must be implemented in subclasses
}

//============================================================

/**
* WebFeed class
* Access periodically-updated image from the web
* Load image in separate thread so as not to block main thread
* Delayed refresh (after error or sucessful load)
*/

class WebFeed extends Feed
{
public int refreshDelay = 2000; // Number of milliseconds to wait between refresh() calls
public PImage loadedImage; // Last loaded image

private PImage loadingImage; // Used for requestImage()
private boolean loading; // Waiting for result from requestImage()?
private boolean requestRefresh; // Set true when a refresh() is wanted
private long refreshAt; // Time (based on millis()) at which to refresh() if requestRefresh true
private int loadFailures; // Number of times the load has failed (since last successful load)

public WebFeed(String description, String locator)
{
super(description, locator);
println("new WebFeed(" + description + ", " + locator + ")");
loadedImage = null;
refresh();
}

public void update()
{
if (loading)
{
if (loadingImage.width == 0)
{
// Image is not yet loaded
}
else if (loadingImage.width == -1)
{
// This means an error occurred during image loading
println("requestImage() failed for " + description + " [" + locator + "]");
loading = false;
loadFailures++;
if (loadFailures <>
{
requestRefresh();
}
}
else
{
// Image is loaded; save a copy and request a fresh copy
println("Loaded: " + description);
loadedImage = loadingImage;
loading = false;
loadFailures = 0;

requestRefresh();
}
}

if (requestRefresh && clock >= refreshAt)
{
refresh();
}
}

public void requestRefresh()
{
requestRefresh = true;
refreshAt = clock + refreshDelay;
println("refreshAt: " + refreshAt + " (now: " + clock + ")");
}

public void refresh()
{
println("Refresh " + description + " [" + locator + "]");
loadingImage = requestImage(locator);
loading = true;
requestRefresh = false;
}

public void display()
{
if (loadedImage == null)
{
displayScrollText(description + " LOADING...");
}
else
{
image(loadedImage, xpos, ypos, width/2, height/2);
displayScrollText(description + " ONLINE");
}
}
}

//============================================================

class CaptureFeed extends Feed
{
public Capture capture; // A local webcam

public CaptureFeed(PApplet p5, String description, String locator, int feedWidth, int feedHeight, int fps)
{
super(description, locator);
capture = new Capture(p5, feedWidth, feedHeight, locator, fps);
}

public void update()
{
if (capture.available())
{
capture.read();
}
}

public void display()
{
image(capture, xpos, ypos);
displayScrollText(description + " LIVE");
}
}

No comments:

Post a Comment