diff --git a/build/shared/readme.txt b/build/shared/readme.txt index a6e7bb8d3..f1d9aca6d 100644 --- a/build/shared/readme.txt +++ b/build/shared/readme.txt @@ -175,10 +175,6 @@ and we don't recommend it at all. nor do we particularly recommend 10.2, if you can avoid it. and if you're running 10.4, processing is the least of your worries. -mouse wheel support only works if you're using java 1.4. the latest -version of java will be available via the software update control -panel. - serial port.. we use rxtx (version 2.1_6) to handle serial i/o, which is included with the processing release. unlike previous releases (anything before 57), it no longer requires separate installation. diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt index 5be759bcd..42aebcc05 100644 --- a/build/shared/revisions.txt +++ b/build/shared/revisions.txt @@ -40,12 +40,35 @@ ABOUT REV 0083 - + shininess(float shiney) takes a float from 0..1 to specify the level of shininess for the current material +- video camera api should now be finalized: + + + that whole thing with passing null or "" to the camera constructor + was really silly. now either one will just give you the default + video input device. + + + added settings() which will show the settings dialog + + + source() takes parameters TUNER, COMPOSITE, SVIDEO or COMPONENT + to select the input source. + + + format() takes parameters NTSC, SECAM or PAL + + + crop(x, y, w, h) (uses the current imageMode from the parent + applet) will crop the video before putting it into its PImage. + this is almost always used internally because qt likes to add + black bars to the image, but you can now specify your own + settings to crop things further + + + noCrop() will remove any cropping, providing a speed increase. + + + there may be bugs.. things were sometimes hanging on my machine + when there were errors + - link() now works when running as an application. also added open(String filename) which will attempt to launch an application using the shell, or open(String args[]) which will do the same with several command line args. -- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . diff --git a/core/PApplet.java b/core/PApplet.java index b5fe3d5ad..74bc27ec2 100644 --- a/core/PApplet.java +++ b/core/PApplet.java @@ -4706,7 +4706,8 @@ public class PApplet extends Applet } static final public int unhex(String what) { - return Integer.parseInt(what, 16); + // has to parse as a Long so that it'll work for numbers bigger than 2^31 + return (int) (Long.parseLong(what, 16)); } // diff --git a/core/todo.txt b/core/todo.txt index 1fecfad90..557c80969 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -131,6 +131,7 @@ o yes, and add nf(int what) so that non-padded version works o but don't put commas into the zero-padded version o make nf/nfs/nfp not so weird o nf(PLUS, ...) nf(PAD, ...) nfc(PLUS, ...) +X unhex was broken for numbers bigger than 2^31 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . diff --git a/todo.txt b/todo.txt index 98c02beb6..fbff2fbc4 100644 --- a/todo.txt +++ b/todo.txt @@ -9,24 +9,38 @@ X get latest sonia from amit X remove particles from current processing X move netscape library out of libs and into build/shared X add serial.stop() just like client/server +X border weirdness in PdeEditor panels on windows (fixed in 82) +o fix macos readme about how to boost memory size, and 1.3 vs 1.4 +X actually, this was already in there camera +o setting the camera should be an index from list() +o there might be multiple cameras with the same name +X no can do, the function takes a String for the device name +o list() should return full list with all sub-components +X find the example code from the board +X grabbing sub-devices from camera in the lib (via list() or whatever) +o actually, need to use numbered indices (multiple w/ same name) +o list should be: "0 - Logitech QuickCam (Blah)" +o and then use the indices (or the str i guess) to choose +X format(NTSC) or PAL or SECAM +X source(COMPOSITE) or SVIDEO or COMPONENT +X settings() brings up settings dialog + _ rename video.Camera to video.Video ? _ VideoInput VideoOutput, SoundInput, SoundOutput or AudioInput/AudioOutput -_ list() should return full list with all sub-components -_ find the example code from the board + _ add prompt() method to Camera ("" means default, null is prompt) _ let them pass in prompt(), not use null -_ setting the camera should be an index from list() -_ grabbing sub-devices from camera in the lib (via list() or whatever) -_ actually, need to use numbered indices (multiple w/ same name) -_ list should be: "0 - Logitech QuickCam (Blah)" -_ and then use the indices (or the str i guess) to choose +_ null is only bringing up settings dialog, that's wrong + +_ port DbnRecorder? +_ do this after beta, not likely to work with java 1.4 on macosx + +_ add prompt() method to serial _ remove PdeXxx prefixes on names, make PdeBase into just "Processing" -_ fix macos readme about how to boost memory size, and 1.3 vs 1.4 - _ update .exe to use new class/package _ update .app to use new class/package _ update linux build and shell scripts for new package @@ -34,9 +48,6 @@ _ update linux build and shell scripts for new package _ make a linux version _ need to fix up the make/dist scripts for linux -fixed in 82 -X border weirdness in PdeEditor panels on windows - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . diff --git a/video/Camera.java b/video/Camera.java index 5602e8715..55d572f30 100644 --- a/video/Camera.java +++ b/video/Camera.java @@ -35,15 +35,26 @@ import quicktime.std.sg.*; import quicktime.util.RawEncodedImage; +// this is the useful ref page +// http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_QTJ/constant-values.html + public class Camera extends PImage implements Runnable { - //implements StdQTConstants, StdQTConstants4, Runnable { + + // there are more, but these are all we'll provide for now + static public final int COMPOSITE = StdQTConstants.compositeIn; // 0 + static public final int SVIDEO = StdQTConstants.sVideoIn; // 1 + static public final int COMPONENT = StdQTConstants.rgbComponentIn; // 2 + static public final int TUNER = StdQTConstants.tvTunerIn; // 6 + + static public final int NTSC = StdQTConstants.ntscIn; + static public final int PAL = StdQTConstants.palIn; + static public final int SECAM = StdQTConstants.secamIn; + PApplet parent; Method cameraEventMethod; - String name; // keep track for error messages + String name; // keep track for error messages (unused) Thread runner; - //PImage borderImage; - //boolean removeBorders = true; boolean available = false; /** Temporary storage for the raw image data read directly from the camera */ @@ -53,18 +64,24 @@ public class Camera extends PImage implements Runnable { public int dataHeight; public int dataRowBytes; + /** True if this image is currently being cropped */ public boolean crop; + public int cropX; public int cropY; public int cropW; public int cropH; - int fps; - RawEncodedImage raw; - SequenceGrabber capture; + public int framerate; + + public RawEncodedImage raw; + public SequenceGrabber capture; + + /** the guy who's doing all the work */ + public SGVideoChannel channel; + static { - //System.out.println("Camera init"); try { QTSession.open(); } catch (QTException e) { @@ -81,11 +98,11 @@ public class Camera extends PImage implements Runnable { public Camera(PApplet parent, int requestWidth, int requestHeight) { - this(parent, "", requestWidth, requestHeight, 30); + this(parent, null, requestWidth, requestHeight, 30); } - public Camera(PApplet parent, int reqWidth, int reqHeight, int fps) { - this(parent, "", reqWidth, reqHeight, fps); + public Camera(PApplet parent, int reqWidth, int reqHeight, int framerate) { + this(parent, null, reqWidth, reqHeight, framerate); } public Camera(PApplet parent, String name, int reqWidth, int reqHeight) { @@ -93,26 +110,10 @@ public class Camera extends PImage implements Runnable { } - /* - quicktime.QTSession.open(); - quicktime.std.sg.SequenceGrabber sg = new quicktime.std.sg.SequenceGrabber(); - quicktime.std.sg.SGVideoChannel sc = new quicktime.std.sg.SGVideoChannel(sg); - quicktime.std.sg.VideoDigitizer vd = sc.getDigitizerComponent(); - println( "dv.getNumberOfInputs :" ); println( vd.getNumberOfInputs() ); println(); -//change line below to set input source - vd.setInput(1); -// - println( "dv.getInput :" ); println( vd.getInput() ); println(); - } catch (Exception e) { - e.printStackTrace(); - } - */ - /** - * If 'name' is the empty string, don't set a specific device, - * which means that QuickTime will use that last device used by - * a QuickTime application. If name is set to null, a prompt - * will show up, allowing the user to choose the good stuff. + * If 'name' is null or the empty string, it won't set a specific + * device, which means that QuickTime will use that last device + * used by a QuickTime application. *
* If the following function: * public void cameraEvent(Camera c) @@ -120,100 +121,48 @@ public class Camera extends PImage implements Runnable { * time a new frame is available from the camera. */ public Camera(PApplet parent, String name, - int requestWidth, int requestHeight, int fps) { + int requestWidth, int requestHeight, int framerate) { this.parent = parent; this.name = name; - this.fps = fps; + this.framerate = framerate; try { - /* - QTSession.open(); - QTRuntimeException.registerHandler(new QTRuntimeHandler() { - public void exceptionOccurred(QTRuntimeException e, - Object obj, String s, boolean flag) { - System.err.println("Problem inside Camera"); - e.printStackTrace(); - } - }); - */ - //System.out.println("0"); - QDRect qdrect = new QDRect(requestWidth, requestHeight); QDGraphics qdgraphics = new QDGraphics(qdrect); - //System.out.println("0a"); - capture = new SequenceGrabber(); - //System.out.println("0b"); capture.setGWorld(qdgraphics, null); - //System.out.println("0c"); - - // CRASHING HERE ON OSX - SGVideoChannel channel = new SGVideoChannel(capture); - //System.out.println("0c1"); + channel = new SGVideoChannel(capture); channel.setBounds(qdrect); - //System.out.println("0c2"); channel.setUsage(2); // what is this usage number? - //System.out.println("0c3"); capture.startPreview(); // maybe this comes later? - //System.out.println("0d"); - PixMap pixmap = qdgraphics.getPixMap(); raw = pixmap.getPixelData(); - //System.out.println("0e"); - + /* if (name == null) { channel.settingsDialog(); } else if (name.length() > 0) { channel.setDevice(name); } - //System.out.println("0f"); - //channel.setDevice("Logitech QuickCam Express-WDM"); - /* - if (showDialog) channel.settingsDialog(); - SGDeviceList list = channel.getDeviceList(0); - System.out.println("count is " + list.getCount()); - for (int i = 0; i < list.getCount(); i++) { - System.out.println(list.getDeviceName(i).getName()); - } - //System.out.println(channel.getSettings()); */ + if ((name != null) && (name.length() > 0)) { + channel.setDevice(name); + } - //int grabWidthBytes = raw.getRowBytes(); dataRowBytes = raw.getRowBytes(); dataWidth = dataRowBytes / 4; - - //System.out.println("row bytes " + raw.getRowBytes() + " " + - // (raw.getRowBytes() / 4)); - //int extraBytes = dataRowBytes - requestWidth*4; - //int extraPixels = extraBytes / 4; - //int videoWidth = requestWidth + extraPixels; dataHeight = raw.getSize() / dataRowBytes; - //System.out.println("height req, actual: " + requestHeight + - // " " + dataHeight); - if (dataWidth != requestWidth) { crop = true; cropX = 0; cropY = 0; cropW = requestWidth; cropH = requestHeight; - - /* - System.out.println("dataWidth is " + dataWidth + - " not " + requestWidth); - if (removeBorders) { - int bpixels[] = new int[dataWidth * requestHeight]; - borderImage = new PImage(bpixels, dataWidth, requestHeight, RGB); - } else { - requestWidth = dataWidth; - } - */ } // initialize my PImage self super.init(requestWidth, requestHeight, RGB); @@ -229,19 +178,17 @@ public class Camera extends PImage implements Runnable { new Class[] { Camera.class }); } catch (Exception e) { // no such method, or an error.. which is fine, just ignore - //e.printStackTrace(); } } catch (StdQTException qte) { //qte.printStackTrace(); int errorCode = qte.errorCode(); - // where's the friggin constant for this? - if (errorCode == -9405) { + if (errorCode == Errors.couldntGetRequiredComponent) { // this can happen when the camera isn't available or // wasn't shut down properly - parent.die("The camera (or VDIG) is not " + - "installed correctly (see readme.txt).", qte); + parent.die("No camera could be found, " + + "or the VDIG is not installed correctly.", qte); } else { parent.die("Error while setting up Camera", qte); } @@ -252,11 +199,20 @@ public class Camera extends PImage implements Runnable { /** - * True if a frame is ready to be read. Example: + * True if a frame is ready to be read. + *
+ * // put this somewhere inside draw
* if (camera.available()) camera.read();
- *
+ *
* Alternatively, you can use cameraEvent(Camera c) to notify you
- * whenever available() is set to true.
+ * whenever available() is set to true. In which case, things might
+ * look like this:
+ *
+ * public void cameraEvent(Camera c) {
+ * c.read();
+ * // do something exciting now that c has been updated
+ * }
+ *
*/
public boolean available() {
return available;
@@ -291,6 +247,13 @@ public class Camera extends PImage implements Runnable {
}
+ /**
+ * Remove the cropping (if any) of the image.
+ * + * By default, cropping is often enabled to trim out black pixels. + * But if you'd rather deal with them yourself (so as to avoid + * an extra lag while the data is moved around) you can shut it off. + */ public void noCrop() { crop = false; } @@ -325,21 +288,7 @@ public class Camera extends PImage implements Runnable { sourceOffset += dataWidth; destOffset += width; } - - /* - if (borderImage != null) { // need to remove borders - raw.copyToArray(0, borderImage.pixels, - 0, borderImage.width * borderImage.height); - int borderIndex = 0; - int targetIndex = 0; - for (int i = 0; i < height; i++) { - System.arraycopy(borderImage.pixels, borderIndex, - pixels, targetIndex, width); - borderIndex += borderImage.width; - targetIndex += width; - } - */ - } else { // just copy directly + } else { // no crop, just copy directly raw.copyToArray(0, pixels, 0, width * height); } //long t2 = System.currentTimeMillis(); @@ -378,7 +327,7 @@ public class Camera extends PImage implements Runnable { } try { - Thread.sleep(1000 / fps); + Thread.sleep(1000 / framerate); } catch (InterruptedException e) { } } } @@ -388,13 +337,13 @@ public class Camera extends PImage implements Runnable { * Set the framerate for how quickly new frames are read * from the camera. */ - public void framerate(int ifps) { - if (ifps <= 0) { + public void framerate(int iframerate) { + if (iframerate <= 0) { System.err.println("Camera: ignoring bad framerate of " + - ifps + " fps."); + iframerate + " fps."); return; } - fps = ifps; + framerate = iframerate; } @@ -436,11 +385,78 @@ public class Camera extends PImage implements Runnable { /** - * Shows the settings dialog for this channel. + * Set the format to ask for from the video digitizer: + * TUNER, COMPOSITE, SVIDEO, or COMPONENT. + *
+ * The constants are just aliases to the constants returned from + * QuickTime's getInputFormat() function, so any valid constant from + * that will work just fine. */ - //public void prompt() { - //channel.settingsDialog(); - //} + public void source(int which) { + try { + VideoDigitizer digitizer = channel.getDigitizerComponent(); + int count = digitizer.getNumberOfInputs(); + for (int i = 0; i < count; i++) { + //System.out.println("format " + digitizer.getInputFormat(i)); + if (digitizer.getInputFormat(i) == which) { + digitizer.setInput(i); + return; + } + } + throw new RuntimeException("The specified source() is not available."); + + } catch (StdQTException e) { + e.printStackTrace(); + throw new RuntimeException("Could not set the video input source."); + } + } + + + /** + * Set the video format standard to use on the + * video digitizer: NTSC, PAL, or SECAM. + *
+ * The constants are just aliases to the constants used for + * QuickTime's setInputStandard() function, so any valid + * constant from that will work just fine. + */ + public void format(int which) { + try { + VideoDigitizer digitizer = channel.getDigitizerComponent(); + digitizer.setInputStandard(which); + } catch (StdQTException e) { + e.printStackTrace(); + //throw new RuntimeException("Could not set the video input format"); + } + } + + + /** + * Show the settings dialog for this input device. + */ + public void settings() { + try { + channel.settingsDialog(); + } catch (StdQTException qte) { + int errorCode = qte.errorCode(); + if (errorCode != Errors.userCanceledErr) { + qte.printStackTrace(); + throw new RuntimeException("error inside Camera.settings()"); + } + } + } + + + /* + public String[] listInputs() { + VideoDigitizer digitizer = channel.getDigitizerComponent(); + int count = digitizer.getNumberOfInputs(); + + String outgoing[] = new String[count]; + //digitizer.setInput(2); // or something + //DigitizerInfo di = digitizer.getDigitizerInfo() + } + */ /**