Oh, except for the camera issue. Which I've made pretty much no progress on, after having beaten my head against it off and on for a couple of weeks. It's reminding me in no uncertain terms of why I no longer write software for a living. This problem is bullshit and I hate working on it. So basically, I'm ready to admit defeat and throw all that plywood on the scrap heap unless someone else solves this problem for me.
Given the choices of "never have a photo booth" and "continue working on this software problem", I gleefully choose the former.
<lj-cut text=" How you can help -- (12%) ">
Things I believe to be true:
The only sensible way to talk to cameras from MacOS is to use ImageCapture.framework.
- IOkit.framework is too low level.
- Gphoto2 doesn't work.
- libptp2 doesn't work.
- ptpcanon doesn't work.
- The official binary-only Canon SDK is junk, according to people who have actually used it.
The Canon Powershot S30 camera supports a bunch of undocumented commands. I have seen Canon's binary-only software do things, with this very camera, like:
- Turn the viewfinder on and off;
- Return a JPEG of the current viewfinder image;
- Take a picture, with flash, and return a JPEG of it without any CF card in the camera.
This camera only advertises two commands, "download file from CF card", and "delete file from CF card". This is according to the Apple CapabilitiesSample demo. Those commands work (e.g., via the SimpleDownload demo.)
Just pasting in the hex codes for the undocumented commands in ICAObjectSendMessagePB.message.messageType doesn't work. I don't know if the commands are actually being sent to the camera, or if the framework is filtering them before they get there, or what.
Wrapping a kICAMessageCameraPassThrough command around these undocumented commands doesn't work either, after cutting and pasting its definition into my code. Maybe PassThrough is a part of the ImageCapture framework, maybe not. It's documented in the ImageCapture SDK, but is not present in any of the installed ImageCapture.framework header files. Is it from some hypothetical future version of the framework? Or is it only supported by some hypothetical camera driver that is not installed by default? I have no idea.
Here's how you can help:
Find me source code that runs on MacOS and that talks to a Canon point-and-shoot camera (I believe they're all the same) and that does something more complicated than "download a file from the CF card; delete it."
Find me someone to talk to who understands and has used ImageCapture.framework in some nontrivial way. This person will be an Apple employee, because as far as I can tell, nobody who is not an Apple employee has ever touched it.
Modify the following code to do something useful, and show me what you did.
Here's some code that doesn't work:
/* A halfassed attempt at using ImageCapture.framework g++ -o test -g -Wall test.mm -framework Carbon */ #import <Carbon/Carbon.h> /* As far as I can tell, this shit should be in /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ ImageCapture.framework/Versions/A/Headers/ICAApplication.h but it's not. Why? I have no idea. */ enum { kICAMessageCameraPassThrough= 'pass', }; enum { kPTPPassThruSend = 0, kPTPPassThruReceive = 1, kPTPPassThruNotUsed = 2, }; typedef struct PTPPassThroughPB { UInt32commandCode; UInt32resultCode; UInt32numOfInputParams; UInt32numOfOutputParams; UInt32params[4]; UInt32dataUsageMode; UInt32flags; UInt32dataSize; UInt8data[1]; } PTPPassThroughPB; int main (int argc, char *argv) { OSErr err = 0; ICAObject list = NULL; // Get the list of image-capturable devices { ICAGetDeviceListPB list_pb; memset(&list_pb, 0, sizeof(list_pb)); err = ICAGetDeviceList(&list_pb, NULL); if (err != noErr) { fprintf (stderr, "device list error = %d\n", err); exit (1); } list = list_pb.object; } // Get the first device ICAObject device = NULL; { ICAGetNthChildPB nth_pb; UInt32 count; ICAGetChildCountPB count_pb; memset(&count_pb, 0, sizeof(count_pb)); count_pb.object = list; err = ICAGetChildCount(&count_pb, nil); if (err != noErr) { fprintf (stderr, "device count error = %d\n", err); exit (1); } count = count_pb.count; if (count <= 0) { fprintf (stderr, "device count = %d\n", (int) count); exit (1); } memset(&nth_pb, 0, sizeof(nth_pb)); nth_pb.parentObject = list; nth_pb.index = 0; err = ICAGetNthChild (&nth_pb, NULL); if (err != noErr) { fprintf (stderr, "first device error = %d\n", err); exit (1); } device = nth_pb.childObject; } // Send the device a message. ICAObjectSendMessagePB pb; memset(&pb, 0, sizeof(pb)); pb.object = device; #if 1 // pb.message.messageType = kICAMessageCameraCaptureNewImage; pb.message.messageType = 0x900b; // Turn viewfinder on #else PTPPassThroughPB *ptb = (PTPPassThroughPB *) malloc (32 * 1024 + sizeof(*ptb)); //ptb->commandCode = 0x901d; //kCanonGetViewfinderImage ptb->commandCode = 0x900b; // turn viewfinder on ptb->numOfInputParams = 0; ptb->numOfOutputParams = 0; ptb->dataUsageMode = kPTPPassThruReceive; ptb->dataSize = 1024; pb.message.messageType = kICAMessageCameraPassThrough; pb.message.startByte= 0; pb.message.dataPtr= ptb; pb.message.dataSize= 1024; pb.message.dataType= kICATypeData; #endif err = ICAObjectSendMessage (&pb, NULL); fprintf (stderr, "status = %d\n", err); return 0; }
If you're giving up on this, can you bring the camera to DNA tonight so I can attempt to make it go? I probably have more time to sit at work and work on this during the day.
Seems to me that if you are faced with a problem which is nearly intractable it might be helpful to change the assumptions. That being said, what is your real ultimate goal with this... to have a photobooth or to have an OS X based photobooth?
And yes, I am assuming that you'll call me an ass for asking that question.
so what's the real ultimate goal with this, to suggest something he might listen to, or to be called an ass?
To suggest something he might listen to obviously.
jesus christ do you newbs do shit like this as some sort of nerd based treasure hunt? GOT BANNED FROM JWZ'S JOURNAL FOR BEING NONHELPFUL WHEN SPECIFICALLY ASKED TO BE HELPFUL: CHECK
i assume this is some sort of aspie attention seeking behavior. plz have it corrected so we dont need to listen to jamie complain about it.
seems to me that if you are faced with a problem which is nearly intractable it might be helpful to change the assumptions.
Um err. um.
shut the fuck up unless you have a solution to our problems, ummm, k, thanks.
Hi. Don't make assumptions. I've known Jamie for around 13 years now. As for 'attention seeking behavior' its not an issue in this case because none of my ego or personal self worth is wrapped up in Jamie taking notice of me.
Now, I know Jamie is kind of smart so I didn't feel I had to lay it out for him in super simple obvious terms. However, I'll take a moment to clarify things. Jamie has a problem trying to get this photobooth thing developed. He seems to be having a bit of problem in part, because of the undocumented and seemingly arcane methods available (or not available as the case may be) under OS X. However, working under OS X is, to be honest, an arbitrary boundary on the problem. He, from what I remember him saying, wants to do this under OS X because that is his preference - not because of any hard technical requirement. Now, we know this *can* be done as evidenced by 'Photoboof' which is what he's basing this project on. However, Photoboof is a windows application. Which is why I asked which is more important to him, having a photobooth or having a photobooth under OS X?
Do you understand why I asked the question now?
I chose OSX because I believed (and still do) that it would be easier than Linux. If someone showed me working code on Linux, I'd consider using that instead (and be sad about it, and surprised).
It's possible that this would be easier on Windows, but like I always say when this comes up, "sewer rat may taste like pumpkin pie, but I'll never know." I have standards, and they trump my desire for, among other things, a photobooth.
Well, I'd think most anything on linux would be mostly doable under OS X. I understand the issue about windows - really I do. I guess what I'm really wondering is if OS X isn't working are there other solutions that would be less resource intensive than the current plan of action. A return to basic assumptions regarding the boundaries of the problem really.
Anyway, you already tried gphoto but you couldn't get it functioning properly under OS X. Why not try just using a linux box and see how it works. The version at gphoto.org even claims to support movie capture.
Also, I'd give it a try under linux myself but I don't actually own a digital camera and the only linux boxes I deal with I keep far far away from me. Personally, I don't like linux much - but they have the best network stack out there right now so I'm kind of stuck using it.
ps. Sewer rat tastes more like squirrel than anything else. Stringier though.
Can't provide any sample code, though, sorry.
I used Canon Capture from http://capture.sourceforge.net/ and took over 60,000 pictures on a road trip across the US using a PowerShot A80. The camera may have insisted on having a CF card (can't remember) in it, but no files were ever written to it -- all transferred over USB.
It was also able to change things like ISO, color saturation, and so on; nifty.
If you want to test the waters first, send me a message with what you need it to do and I can do some quick tests.
I did a quick search through the Apple mailing lists and came up someone who might be able to help: Manchuen Dino Tang (tang@mac.com). From the looks of it he's an Apple employee working with image capture and USB.
ptb->dataSize = 1024;
pb.message.dataSize = 1024;
are those right?
They're commented out, so that shouldn't matter. See the
further up.
hurmph I guess my eye doctor is right about needing reading glasses.
:(
http://freakshowsoftware.com/
PhotoBooth-Like application that supports just about any webcam, It can use mac-cam drivers to support cameras OSX doesn't, and mac-cam (http://webcam-osx.sourceforge.net/) lists Canon cameras.
I'm not talking about webcams. I already have code that does that. They all suck in low light. I'm talking about a digital still camera, with a flash. And that "mac-cam" thing lists "Canyon" cameras, not "Canon". I don't think Canon makes a webcam.
I've been watching these photobooth discussions for awhile and finally had to create an account so I could reply since something that seems painfully obvious to me has repeatedly been passed over.
Is this really a software issue?
I'm not familiar with the Cannon Powershot, but I can see that it has an A/V port and suspect it probably works similar to the A/V port on the various Nikon coolpixes I have laying around. If it does then this could be a dirt simple solution.
If the Powershot doesn't work like this then I appologize for wasting your time with the idea (and I completely understand not wanting to by more hardware but a used Coolpix is pretty cheap).
The way the Coolpix A/V works is you plug in a simple phono->RCA cable and the screen is then sent out as NTSC instead of displaying on the back of the camera. Instant live video. No software no muss no fuss. You can still use the USB connection for triggering shots and downloading them.
Either run the A/V to a cheap 13" TV (or a projector or whatever else you want..it's normal NTSC video) or if the computer has video input you can make things complex and bring it in that way for display I suppose.
If that doesn't help you may want to look at some KAP (Kite Aerial Photography) sites as the Cannons are fairly popular with them and a lot of those guys will run video over a wireless link for previews....so I suspect that the Cannon A/V does work as I suspect.
Preview problem solved, and from your previous posts it sounds like the issue of snapping and downloading single frames was already solved some time ago.
"You can still use the USB connection for triggering shots and downloading them."
I have no way of remotely triggering shots, that's one of the "undocumented" camera commands, so I'm back to the first problem again. The only "documented" commands are "copy file from CF card" and "delete file from CF card". I guess I could use a relay and tear apart the physical fire button, but then there'd have to be a CF card in the camera, and that would make the turnaround time on getting the pictures out be quite a few seconds. Plus, the card would wear out.
Guess my memory is going and I should have reviewed the earlier posts. I thought that problem had already been solved and it was just the preview still causing fits.
Wish I knew more about the Cannons so I could offer more insight. Sorry.
You wrote before:
and I also thought this combined with the A/V-out would do the trick. I wrote that you could use the port to get video, but I guess you were thinking "I'm not worried about the video at the moment!"
Well, I'm assuming "can fire the camera and get the picture out" means it does all that without a CF-card, if it needs a card then just stop reading now. If gphoto2 is capable of that, then I can think of a solution, at least on a Linux box: tvtime --slave (ignores keyboard input) and a program that fires gphoto2. Of course talk is cheap..
At the risk of being less helpful than usual (which is quite a feat in itself), have you tried running USB Prober (in /Developer/Applications/Utilites) and capturing the conversation that the Canon software has with the camera? There might be some extra commands that are required to get the camera into the right "mode", or something.
Of course I tried running USB Prober on my machine, and it kernel paniced, but I'm hoping that's just because of something I've done wrong here, not because USB Prober no longer works.
(I'm a packet trace kind of a guy - the bits on the wire never lie, whereas the specs and SDK often do. At my last job we had a $30000 USB/Firewire/ATA sniffer and analyser - those things let you see through the lies and bugs like nothing else...)
I've yet to figure out how to cross the layer between ImageCapture and IOkit, so even if I knew what packets to throw at it, I don't know how. (Without, like, hardcoding in a particular vendor and device ID or something, and using only IOkit.) And the IOkit USB demos aren't any clearer to me than the ImageCapture demos.
I don't know if I'm correct, but I suspect these folks might have some tips: http://www.engadget.com/2007/02/04/gigapan-robot-snaps-panoramic-views-assembles-results/
Well, looking at it from another direction, it seems all you want to do is hit the button on top from software.
It may be overkill, but it seems like what you want is some lego.
I'm not sure if you have stumbled across this already, but this post form 2005 on an apple mailing list suggest what you want has been done before, I think:
http://lists.apple.com/archives/Usb/2005/Feb/msg00092.html
(to be read bottom-up I'm afraid)
And hey, it says exactly what violentbloom noticed in your #else part (which I assume is an earlier test?):
"You are sending too much data. You only need to send 2 bytes.
buf = malloc( 2 + sizeof(PTPPassThroughPB) - 1 );
"
If this does not help, perhaps you could try to find out if something similar exists on other platforms, in an open source form, to look at what they send?
Yes, I have also linked to that very thread like five times. And tried to mail one of the participants, who didn't write back.
Oops, sorry!
Rats. But I did notice one thing: Canon doesn't mention the S30 as having PTP support on Mac OS X.
Have you seen this page (Canon PowerShot Series Transfer Protocol)?
Reading that thread further, it does not end well:
Q: "Do you know how to get the current viewfinder image or an image that has been captured to memory (and not to memory card) from a Canon PowerShot camera? I think that this is a vendor related issue, and I've tried it many times without success.
Downloading an image that is already on the card is no problem, but I'd like to get the image that is still in internal memory. I know that there must be a solution, because in the Canon ImageCapture application it is working."
A: "All those go through vendor specific code. I have no idea what was going on. Even if I do, I could not tell you cause I would be bound by NDA. Sorry."
I wonder if he's talking about the undocumented codes there, or if it's something even more vendor specific (i.e. not exposed in ptp codes).
I mean, flame away, but wouldn't it be easier at this point to just hack the camera and use a relay to hit the shutter button and then just grab the image using the primitives you have? I know my old Powershot used to dump the viewfinder image out the AV port, so that might do.
Ugly, I know.
Contact the people at Seattle's McLeod Residence -- they have a photobooth that posts to Flickr, and it might be the same as what you're looking to have.
Also, Leopard has a new QTKit Capture API which may do what you want. I don't know if it supports PTP, but it defnitely supports USB(VDC), FireWire(IIDC), and DV, and it's Cocoa so it doesn't hurt.
Not entirely. I am trying to do something very similar to your project. I have access to a Canon PowerShot SD500. When I tried using Canon's own Remote Capture application, the Camera Windows application didn't even give me the option to run it. After digging around in the manuals, I found a note that the shutter can't be activated remotely on the SD500. I dug around on the net and found the following tidbit:
"Statement from Canon SDK: As a reminder, PowerShots A410, A420, A430, A530, A540, A610, A630, A700, A710 IS, S10, S20, SD10, SD20, SD30, SD40, SD200, SD300, SD400, SD430, SD450, SD500, SD550, SD600, SD630, SD700 IS, SD800 IS, and SD900 do not support remote control or video out operation via the SDK."
So some Canon point-and-shoot cameras don't support remote capture at all. Just another pitfall to be aware of.