/* * freeFormed.org Video and Photo Posting Application * by Catherine Colman 2006 MobileApps Design Class ITP * * Special thanks to Shawn Van Every and Micheal Sharon for code blocks * */ import java.io.IOException; import java.io.*; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import javax.microedition.io.SocketConnection; import javax.microedition.lcdui.*; import javax.microedition.media.*; import javax.microedition.media.control.*; import javax.microedition.midlet.MIDlet; import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; public class catVideoMIDlet extends MIDlet implements CommandListener { private Display mDisplay; private String phone_number = getAppProperty("Phone_number"); private Form mMainForm; private Command mExitCommand, mVideoCommand; private Command mVideoStopCommand, mVideoCaptureCommand, mPhotoSendCommand; private Command mVideoPlayCommand, mVideoSendCommand,mPhotoCaptureCommand; private Command mAddText, mGetCircles; private Player mPlayer; private VideoControl mVideoControl; private ByteArrayOutputStream outStream = new ByteArrayOutputStream(); private ByteArrayInputStream inStream; private RecordControl rc; private ByteArrayOutputStream frameOutStream; private ByteArrayInputStream frameInStream; private boolean videoCaptured = false; private boolean captureSetup = false; boolean captureRunning = false; boolean videoPlaying = false; private TextField titleTextfield; private TextField descriptionTextfield; private TextField privacyTextfield; private String title = ""; private String description = ""; private String privacy = ""; private boolean addingText = false; private Video video; public catVideoMIDlet() { mExitCommand = new Command("Exit", Command.EXIT, 0); mVideoCommand = new Command("Show Camera", Command.SCREEN, 0); mVideoCaptureCommand = new Command("Start Capture", Command.SCREEN, 0); mPhotoCaptureCommand = new Command("Take Picture", Command.SCREEN, 0); mVideoPlayCommand = new Command("Play Video", Command.SCREEN, 0); mVideoStopCommand = new Command("Stop", Command.SCREEN, 0); mVideoSendCommand = new Command("Send Video", Command.SCREEN, 0); mPhotoSendCommand = new Command("Send Photo", Command.SCREEN, 0); mAddText = new Command("Add Text", Command.SCREEN, 0); mGetCircles = new Command("Get Circles", Command.SCREEN, 0); mMainForm = new Form("Video Streamer"); mMainForm.addCommand(mExitCommand); String video_support = System.getProperty("video.encodings"); if (video_support != null && video_support.length() > 0) { mMainForm.append("To take a picture or shoot some video select show camera from your menu"); mMainForm.addCommand(mVideoCommand); mMainForm.addCommand(mVideoCaptureCommand); mMainForm.addCommand(mVideoPlayCommand); mMainForm.addCommand(mVideoStopCommand); mMainForm.addCommand(mVideoSendCommand); mMainForm.addCommand(mPhotoSendCommand); mMainForm.addCommand(mAddText); mMainForm.addCommand(mGetCircles); } else { mMainForm.append("Cannot use this device to shoot video."); } mMainForm.setCommandListener(this); } public void startApp() { mDisplay = Display.getDisplay(this); mDisplay.setCurrent(mMainForm); } public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable s) { if (c.getCommandType() == Command.EXIT) { destroyApp(true); notifyDestroyed(); } else if (c == mVideoCommand) { showVideoCamera(); } else if (c == mVideoCaptureCommand) { videoCapture(); } else if (c == mPhotoCaptureCommand) { video = new Video(this); video.start(); } else if (c == mVideoStopCommand) { if (captureRunning) { stopCapture(); } else if (videoPlaying) { stopVideo(); } } else if (c == mVideoPlayCommand) { playVideo(); } else if (c == mVideoSendCommand) { sendCapturedVideo(); } else if (c == mVideoSendCommand) { sendCapturedPhoto(); } else if (c == mAddText) { addText(); } else if (c == mGetCircles) { getCircles(); } } private void getCircles() { try { GetCircles getCircles = new GetCircles(this); getCircles.start(); } catch (Exception e) { handleException(e); } } public class GetCircles extends Thread implements CommandListener{ catVideoMIDlet midlet; public GetCircles(catVideoMIDlet midlet) { this.midlet = midlet; } final String URL = "http://www.freeformed.org/javatest.php?userid=1"; final String TITLE = "Your Groups"; Form form = new Form("ChoiceGroup"); Vector descriptions = new Vector(); ChoiceGroup multiGroup = new ChoiceGroup("Choose any", ChoiceGroup.MULTIPLE); TextBox textBox = new TextBox("", "", 256, TextField.ANY); Command backCmd = new Command("Back", Command.BACK, 0); public void commandAction(Command c, Displayable d) { if (c == List.SELECT_COMMAND) { System.out.println("got here"); String text = (String) descriptions.elementAt(multiGroup.getSelectedIndex()); if (textBox.getMaxSize() < text.length()) textBox.setMaxSize(text.length()); textBox.setString(text); mDisplay.setCurrent(textBox); } } public void run() { try { HttpConnection httpConnection = (HttpConnection) Connector.open(URL); KXmlParser parser = new KXmlParser(); System.out.println("Grabbing XML and parsing"); parser.setInput(new InputStreamReader(httpConnection.openInputStream())); System.out.println("looking for first tag"); parser.nextTag(); parser.require(XmlPullParser.START_TAG, null, "feed"); while (parser.nextTag () != XmlPullParser.END_TAG) readStory(parser); parser.require(XmlPullParser.END_TAG, null, "feed"); parser.next(); parser.require(XmlPullParser.END_DOCUMENT, null, null); } catch (Exception e) { e.printStackTrace(); descriptions.addElement(e.toString()); form.append(multiGroup); multiGroup.append("Error", null); } } // Read a story and append it to the list void readStory(KXmlParser parser) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, null, "item"); String title = null; String description = null; while (parser.nextTag() != XmlPullParser.END_TAG) { parser.require(XmlPullParser.START_TAG, null, null); String name = parser.getName(); String text = parser.nextText(); System.out.println ("<"+name+">"+text); if (name.equals("title")) title = text; else if (name.equals("description")) description = text; parser.require(XmlPullParser.END_TAG, null, name); } parser.require(XmlPullParser.END_TAG, null, "item"); if (title != null) { descriptions.addElement(""+description); multiGroup.append(title, null); } } } private void addText() { if (!addingText) { Form mTextForm = new Form("Adding Text"); titleTextfield = new TextField("Title", title, 128, TextField.ANY); descriptionTextfield = new TextField("Description", description, 256, TextField.ANY); privacyTextfield = new TextField("Privacy", privacy, 128, TextField.ANY); mTextForm.append(titleTextfield); mTextForm.append(descriptionTextfield); mTextForm.append(privacyTextfield); mTextForm.addCommand(mAddText); mTextForm.setCommandListener(this); mDisplay.setCurrent(mTextForm); addingText = true; } else { title = titleTextfield.getString(); description = descriptionTextfield.getString(); privacy = privacyTextfield.getString(); mDisplay.setCurrent(mMainForm); addingText = false; } } private void showVideoCamera() { try { mPlayer = Manager.createPlayer("capture://video"); mPlayer.realize(); mVideoControl = (VideoControl) mPlayer.getControl("VideoControl"); Canvas canvas = new CameraCanvas(this, mVideoControl, CameraCanvas.VIDEO_CAPTURE); canvas.addCommand(mVideoCaptureCommand); canvas.addCommand(mPhotoCaptureCommand); canvas.addCommand(mVideoStopCommand); canvas.setCommandListener(this); mDisplay.setCurrent(canvas); mPlayer.start(); } catch (IOException ioe) { handleException(ioe); } catch (MediaException me) { handleException(me); } } public void setupCapture() { rc = (RecordControl) mPlayer.getControl("RecordControl"); rc.setRecordStream(outStream); captureSetup = true; } public void videoCapture() { if (!captureRunning) { if (!captureSetup) { setupCapture(); } captureRunning = true; try { rc.startRecord(); mPlayer.start(); } catch (MediaException me) { handleException(me); } } } public void stopCapture() { if (captureRunning) { try { rc.stopRecord(); rc.commit(); mPlayer.stop(); mPlayer.close(); inStream = new ByteArrayInputStream(outStream.toByteArray()); videoCaptured = true; mDisplay.setCurrent(mMainForm); captureRunning = false; } catch (MediaException me) { handleException(me); } catch (IOException e) { handleException(e); } } } public void stopVideo() { try { mPlayer.stop(); mPlayer.close(); mDisplay.setCurrent(mMainForm); videoPlaying = false; } catch (MediaException me) { handleException(me); } } public void playVideo() { if (videoCaptured) { try { mPlayer = Manager.createPlayer(inStream,"video/3gpp"); mPlayer.realize(); // get video control mVideoControl = (VideoControl) mPlayer.getControl("VideoControl"); Canvas canvas = new CameraCanvas(this, mVideoControl, CameraCanvas.VIDEO_PLAYBACK); canvas.addCommand(mVideoStopCommand); canvas.addCommand(mVideoSendCommand); canvas.setCommandListener(this); mDisplay.setCurrent(canvas); mPlayer.start(); } catch (MediaException me) { handleException(me); } catch (IOException e) { handleException(e); } } } public byte[] captureFrame() { byte[] rawPixels = new byte[0]; try { rawPixels = mVideoControl.getSnapshot(null); } catch (MediaException me) { handleException(me); } return rawPixels; } public void sendCapturedPhoto() { try { URLEncoder encoder = new URLEncoder(); PhotoPoster photoposter = new PhotoPoster("http://www.freeformed.org/up.php?title=" + encoder.encode(title, "UTF-8") + "&description=" + encoder.encode(description, "UTF-8")+ "&phone_number=" + encoder.encode(phone_number, "UTF-8") + "&privacy=" + encoder.encode(privacy, "UTF-8"), "post.png", outStream.toByteArray()); photoposter.start(); } catch (Exception e) { handleException(e); } } public void sendCapturedFrame(byte[] outBytes) { try { // Send data from outputstream frameOutStream.write(outBytes); } catch (IOException e) { handleException(e); } } public void sendCapturedVideo() { try { URLEncoder encoder = new URLEncoder(); HTTPPoster poster = new HTTPPoster("http://www.freeformed.org/up.php?title=" + encoder.encode(title, "UTF-8") + "&description=" + encoder.encode(description, "UTF-8") + "&phone_number=" + encoder.encode(phone_number, "UTF-8")+ "&privacy=" + encoder.encode(privacy, "UTF-8"), "post.3gp", outStream.toByteArray()); poster.start(); } catch (Exception e) { handleException(e); } } class Video extends Thread { catVideoMIDlet midlet; public Video(catVideoMIDlet midlet) { this.midlet = midlet; } public void run() { capturePhoto(); } public byte[] capturePhoto() { byte[] rawPixels = new byte[0]; try { rawPixels = mVideoControl.getSnapshot(null); /* byte[] raw = mVideoControl.getSnapshot(null); */ Image image = Image.createImage(rawPixels, 0, rawPixels.length); mMainForm.append(image); mDisplay.setCurrent(mMainForm); mPlayer.close(); mPlayer = null; mVideoControl = null; rawPixels = null; } catch (MediaException me) { } return rawPixels; } }; private void handleException(Exception e) { Alert a = new Alert("Exception", e.toString(), null, null); a.setTimeout(Alert.FOREVER); mDisplay.setCurrent(a, mMainForm); } private void showAlert(String sToPrint) { Alert a = new Alert("Exception", sToPrint, null, null); a.setTimeout(Alert.FOREVER); mDisplay.setCurrent(a, mMainForm); } public class PhotoPoster extends Thread { String url; String fileName; byte[] outputArray; PhotoPoster(String _url, String _fileName, byte[] _outputArray) { url = _url; fileName = _fileName; outputArray = _outputArray; } public void run() { HttpConnection c = null; InputStream is = null; OutputStream os = null; String b = "Server Response:"; TextBox t = null; try { c = (HttpConnection) Connector.open(url); c.setRequestMethod(HttpConnection.POST); String boundary = "---7d43722015402c8---"; String boundaryMessage = "--" + boundary + "\r\n" + "Content-Disposition: form-data;" + "name=\"bytes\"; filename=\"" + fileName + "\r\n" + "Content-Type: " + "image/png" + "\r\n" + "\r\n"; String endBoundary = "\r\n" + "--" + boundary + "\r\n"; byte[] endBoundaryBytes = endBoundary.getBytes(); byte[] boundaryMessageBytes = boundaryMessage.getBytes(); c.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary); DataOutputStream dos = new DataOutputStream(c.openOutputStream()); // Write Boundary Message for(int i=0; i < boundaryMessageBytes.length; i++) { dos.writeByte(boundaryMessageBytes[i]); } // Write Data for(int i = 0; i < outputArray.length; i++) { dos.writeByte(outputArray[i]); } // End Data for(int i = 0; i < endBoundaryBytes.length; i++) { dos.writeByte(endBoundaryBytes[i]); } dos.flush(); // Read input is = c.openDataInputStream(); int ch; while ((ch = is.read()) != -1) { b = b + (char) ch; } dos.close(); is.close(); c.close(); showAlert(b); } catch (Exception e) { handleException(e); } } } public class HTTPPoster extends Thread { String url; String fileName; byte[] outputArray; HTTPPoster(String _url, String _fileName, byte[] _outputArray) { url = _url; fileName = _fileName; outputArray = _outputArray; } public void run() { HttpConnection c = null; InputStream is = null; OutputStream os = null; String b = "Server Response:"; TextBox t = null; try { c = (HttpConnection) Connector.open(url); c.setRequestMethod(HttpConnection.POST); String boundary = "---7d43722015402c8---"; String boundaryMessage = "--" + boundary + "\r\n" + "Content-Disposition: form-data;" + "name=\"bytes\"; filename=\"" + fileName + "\r\n" + "Content-Type: " + "video/3gpp" + "\r\n" + "\r\n"; String endBoundary = "\r\n" + "--" + boundary + "\r\n"; byte[] endBoundaryBytes = endBoundary.getBytes(); byte[] boundaryMessageBytes = boundaryMessage.getBytes(); c.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary); DataOutputStream dos = new DataOutputStream(c.openOutputStream()); // Write Boundary Message for(int i=0; i < boundaryMessageBytes.length; i++) { dos.writeByte(boundaryMessageBytes[i]); } // Write Data for(int i = 0; i < outputArray.length; i++) { dos.writeByte(outputArray[i]); } // End Data for(int i = 0; i < endBoundaryBytes.length; i++) { dos.writeByte(endBoundaryBytes[i]); } dos.flush(); // Read input is = c.openDataInputStream(); int ch; while ((ch = is.read()) != -1) { b = b + (char) ch; } dos.close(); is.close(); c.close(); showAlert(b); } catch (Exception e) { handleException(e); } } } public class FrameTimerTask extends TimerTask { public void run() { captureFrame(); } } /** * This class encodes strings for sending over HTTP. It replaces the URLEncoder * class from the J2SE. * @author yaniv & tsahi */ public class URLEncoder { public String encode(String s, String enc) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DataOutputStream dOut = new DataOutputStream(bOut); StringBuffer ret = new StringBuffer(); //return value dOut.writeUTF(s); ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); bIn.read(); bIn.read(); int c = bIn.read(); while (c >= 0) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '-' || c == '*' || c == '_') ret.append((char)c); else if (c == ' ') ret.append('+'); else { if (c < 128) { appendHex(c, ret); } else if (c < 224) { appendHex(c, ret); appendHex(bIn.read(), ret); } else if (c < 240) { appendHex(c,ret); appendHex(bIn.read(), ret); appendHex(bIn.read(), ret); } } c = bIn.read(); } return ret.toString(); } private void appendHex(int arg0, StringBuffer buff){ buff.append('%'); if (arg0 < 16) buff.append('0'); buff.append(Integer.toHexString(arg0)); } } }