From 7be7febfce5b98458cf24480d741ea888ceb04fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20Nore=C3=B1a?= Date: Fri, 1 Mar 2013 13:12:58 +0100 Subject: [PATCH] - addes plugin videoDarwin to Gem. It's not necesary for LMS but Gem fails compiling whitout it. --- .../plugins/videoDarwin/Darwin-videoplugin.pd | 2 + src/Gem/plugins/videoDarwin/Makefile.am | 40 + src/Gem/plugins/videoDarwin/videoDarwin.cpp | 689 ++++++++++++++++++ src/Gem/plugins/videoDarwin/videoDarwin.h | 106 +++ 4 files changed, 837 insertions(+) create mode 100644 src/Gem/plugins/videoDarwin/Darwin-videoplugin.pd create mode 100644 src/Gem/plugins/videoDarwin/Makefile.am create mode 100644 src/Gem/plugins/videoDarwin/videoDarwin.cpp create mode 100644 src/Gem/plugins/videoDarwin/videoDarwin.h diff --git a/src/Gem/plugins/videoDarwin/Darwin-videoplugin.pd b/src/Gem/plugins/videoDarwin/Darwin-videoplugin.pd new file mode 100644 index 0000000..1c88a7d --- /dev/null +++ b/src/Gem/plugins/videoDarwin/Darwin-videoplugin.pd @@ -0,0 +1,2 @@ +#N canvas 8 49 505 112 10; +#X text 89 47 Nothing special about this backend...; diff --git a/src/Gem/plugins/videoDarwin/Makefile.am b/src/Gem/plugins/videoDarwin/Makefile.am new file mode 100644 index 0000000..206c759 --- /dev/null +++ b/src/Gem/plugins/videoDarwin/Makefile.am @@ -0,0 +1,40 @@ + +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CPPFLAGS = -I$(top_srcdir)/src @GEM_EXTERNAL_CPPFLAGS@ + +pkglib_LTLIBRARIES= +gemhelpdir=$(pkglibdir) +dist_gemhelp_DATA = + +if VIDEODARWIN +pkglib_LTLIBRARIES+=gem_videoDarwin.la +dist_gemhelp_DATA +=Darwin-videoplugin.pd +endif + +gem_videoDarwin_la_CXXFLAGS = +gem_videoDarwin_la_LDFLAGS = -module -avoid-version -shared +if WINDOWS +gem_videoDarwin_la_LDFLAGS += -no-undefined +endif +gem_videoDarwin_la_LIBADD = + +# RTE +gem_videoDarwin_la_CXXFLAGS += @GEM_RTE_CFLAGS@ @GEM_ARCH_CXXFLAGS@ +gem_videoDarwin_la_LDFLAGS += @GEM_RTE_LIBS@ @GEM_ARCH_LDFLAGS@ +# flags for building Gem externals +gem_videoDarwin_la_CXXFLAGS += @GEM_EXTERNAL_CFLAGS@ +gem_videoDarwin_la_LIBADD += -L$(top_builddir) @GEM_EXTERNAL_LIBS@ +# gem_videoDarwin_la @MOREFLAGS@ + +# Dependencies +gem_videoDarwin_la_CXXFLAGS += +gem_videoDarwin_la_LIBADD += @GEM_FRAMEWORK_QUICKTIME@ @GEM_FRAMEWORK_CARBON@ + +# convenience symlinks +include $(srcdir)/../symlink_ltlib.mk + + +### SOURCES +gem_videoDarwin_la_SOURCES= videoDarwin.cpp videoDarwin.h + + diff --git a/src/Gem/plugins/videoDarwin/videoDarwin.cpp b/src/Gem/plugins/videoDarwin/videoDarwin.cpp new file mode 100644 index 0000000..06c298b --- /dev/null +++ b/src/Gem/plugins/videoDarwin/videoDarwin.cpp @@ -0,0 +1,689 @@ +/* + * videoDarwin.cpp + * gem_darwin + * + * Created by James Tittle on Fri Jul 12 2002. + * Copyright (c) 2002-2005 James Tittle & Chris Clepper + * Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at + * + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined __APPLE__ && defined __x86_64 +#warning unconditionally disabling QuickTime/Carbon on OSX/64bit +// with OSX10.6, apple has removed loads of Carbon functionality (in 64bit mode) +// LATER make this a real check in configure +# undef HAVE_QUICKTIME +# undef HAVE_CARBON +#endif + +#if defined HAVE_CARBON && defined HAVE_QUICKTIME +# define HAVE_VIDEODARWIN +#endif + +#ifdef HAVE_VIDEODARWIN +#include "videoDarwin.h" +#include "Gem/RTE.h" +#include "plugins/PluginFactory.h" + +using namespace gem::plugins; + +#include // needed for Unix file open() type functions +#include +#include /* JMZ thinks that _this_ is needed for open() */ + +#define DEFAULT_WIDTH 320 +#define DEFAULT_HEIGHT 240 + +static std::string pascal2str(const Str255 pstr) { + const unsigned char*cstr=static_cast(pstr); + const char*str=(const char*)(cstr+1); + const size_t length=cstr[0]; + return std::string(str, length); +} + + + +REGISTER_VIDEOFACTORY("Darwin", videoDarwin); + +videoDarwin :: videoDarwin() + : videoBase("darwin", 0), + m_newFrame(false), + m_srcGWorld(NULL), + m_quality(channelPlayNormal), + m_colorspace(GL_YCBCR_422_GEM), + m_inputDevice(0) //set to the first input device +{ + m_width= DEFAULT_WIDTH; + m_height=DEFAULT_HEIGHT; + + m_image.image.xsize = 800; + m_image.image.ysize = 600; + m_image.image.setCsizeByFormat(GL_BGRA_EXT); + m_image.image.allocate(); + + //initSeqGrabber(); + provide("dv"); + provide("iidc"); + provide("analog"); +} + +//////////////////////////////////////////////////////// +// Destructor +// +///////////////////////////////////////////////////////// +videoDarwin :: ~videoDarwin() +{ + close(); + if (m_vc) { + if (::SGDisposeChannel(m_sg, m_vc)) { + error ("Unable to dispose a video channel"); + } + m_vc = NULL; + } + if (m_sg) { + if (::CloseComponent(m_sg)) { + error("Unable to dispose a sequence grabber component"); + } + m_sg = NULL; + if (m_srcGWorld) { + ::DisposeGWorld(m_srcGWorld); + m_srcGWorld = NULL; + } + } +} +bool videoDarwin :: openDevice(gem::Properties&props) { + applyProperties(props); + bool success=initSeqGrabber(); + if(NULL==m_sg)success=false; + if(success) + applyProperties(props); + else + destroySeqGrabber(); + + return success; +} +void videoDarwin :: closeDevice(void) { + destroySeqGrabber(); +} + +//////////////////////////////////////////////////////// +// render +// +///////////////////////////////////////////////////////// +bool videoDarwin :: grabFrame() +{ + OSErr err; + + err = SGIdle(m_sg); + + if (err != noErr){ + error("SGIdle failed with error %d",err); + m_haveVideo = 0; + // return false; + } else { + //this doesn't do anything so far + //VDCompressDone(m_vdig,frameCount,data,size,similar,time); + //err = SGGrabFrameComplete(m_vc,frameCount,done); + //if (err != noErr) error("SGGrabCompressComplete failed with error %d",err); + //post("SGGrabFramecomplete done %d framecount = %d",done[0],frameCount); + + m_haveVideo = 1; + m_newFrame = true; + } + if (!m_haveVideo) + { + post("no video yet"); + return true; + } + m_image.newimage = m_newFrame; + m_newFrame = false; + + return true; +} + +//////////////////////////////////////////////////////// +// startTransfer +// +///////////////////////////////////////////////////////// +bool videoDarwin :: startTransfer() +{ + OSErr err = noErr; + + SGStartPreview(m_sg); + m_haveVideo = true; + m_image.newimage = true; + return true; +} + +//////////////////////////////////////////////////////// +// stopTransfer +// +///////////////////////////////////////////////////////// +bool videoDarwin :: stopTransfer() +{ + OSErr err = noErr; + + //might need SGPause or SGStop here + err = SGStop(m_sg); + if (err != noErr)error("SGStop failed with error %d",err); + return true; +} + +bool videoDarwin :: initSeqGrabber() +{ + OSErr anErr; + Rect srcRect = {0,0, m_height, m_width}; + SGDeviceList devices; + short deviceCount = 0; + + m_sg = OpenDefaultComponent(SeqGrabComponentType, 0); + if(m_sg==NULL){ + error("could not open default component"); + return false; + } + anErr = SGInitialize(m_sg); + if(anErr!=noErr){ + error("could not initialize SG error %d",anErr); + return false; + } + + anErr = SGSetDataRef(m_sg, 0, 0, seqGrabDontMakeMovie); + if (anErr != noErr){ + error("dataref failed with error %d",anErr); + } + + anErr = SGNewChannel(m_sg, VideoMediaType, &m_vc); + if(anErr!=noErr){ + error("could not make new SG channnel error %d",anErr); + return false; + } + + enumerate(); + anErr = SGGetChannelDeviceList(m_vc, sgDeviceListIncludeInputs, &devices); + if(anErr!=noErr){ + error("could not get SG channnel Device List"); + }else{ + deviceCount = (*devices)->count; + m_inputDevice = (*devices)->selectedIndex; + } + + /* device selection */ + if(m_devicenum>=0) + m_inputDevice=m_devicenum; + else if (!m_devicename.empty()) { + int i; + const int maxcount=(deviceCount= 0 && m_inputDevice < deviceCount) {//check that the device is not out of bounds + std::string devname=pascal2str((*devices)->entry[m_inputDevice].name); + post("SGSetChannelDevice trying[%d] %s", m_inputDevice, devname.c_str()); + } + anErr = SGSetChannelDevice(m_vc, (*devices)->entry[m_inputDevice].name); + if(anErr!=noErr) error("SGSetChannelDevice returned error %d",anErr); + + anErr = SGSetChannelDeviceInput(m_vc,m_inputDeviceChannel); + if(anErr!=noErr) error("SGSetChannelDeviceInput returned error %d",anErr); + + //grab the VDIG info from the SGChannel + m_vdig = SGGetVideoDigitizerComponent(m_vc); + VideoDigitizerError vdigErr = VDGetDigitizerInfo(m_vdig,&m_vdigInfo); //not sure if this is useful + + Str255 vdigName; + memset(vdigName,0,255); + vdigErr = VDGetInputName(m_vdig,m_inputDevice,vdigName); + post("vdigName is %s",pascal2str(vdigName).c_str()); + + Rect vdRect; + vdigErr = VDGetDigitizerRect(m_vdig,&vdRect); + post("digitizer rect is top %d bottom %d left %d right %d",vdRect.top,vdRect.bottom,vdRect.left,vdRect.right); + + vdigErr = VDGetActiveSrcRect(m_vdig,0,&vdRect); + post("active src rect is top %d bottom %d left %d right %d",vdRect.top,vdRect.bottom,vdRect.left,vdRect.right); + + anErr = SGSetChannelBounds(m_vc, &srcRect); + if(anErr!=noErr){ + error("could not set SG ChannelBounds "); + } + + anErr = SGSetVideoRect(m_vc, &srcRect); + if(anErr!=noErr){ + error("could not set SG Rect "); + } + + anErr = SGSetChannelUsage(m_vc, seqGrabPreview); + if(anErr!=noErr){ + error("could not set SG ChannelUsage "); + } + SGSetChannelPlayFlags(m_vc, m_quality); + OSType pixelFormat=0; + m_image.image.xsize = m_width; + m_image.image.ysize = m_height; + + if (m_colorspace==GL_BGRA_EXT){ + m_image.image.setCsizeByFormat(GL_RGBA_GEM); + m_rowBytes = m_width*4; + pixelFormat=k32ARGBPixelFormat; + post ("using RGB"); + } else { + m_image.image.setCsizeByFormat(GL_YCBCR_422_APPLE); + m_rowBytes = m_width*2; + pixelFormat=k422YpCbCr8PixelFormat; + post ("using YUV"); + } + m_image.image.reallocate(); + anErr = QTNewGWorldFromPtr (&m_srcGWorld, + pixelFormat, + &srcRect, + NULL, + NULL, + 0, + m_image.image.data, + m_rowBytes); + + if (anErr!= noErr) { + error("%d error at QTNewGWorldFromPtr", anErr); + return false; + } + if (NULL == m_srcGWorld) { + error("could not allocate off screen"); + return false; + } + SGSetGWorld(m_sg,(CGrafPtr)m_srcGWorld, NULL); + SGStartPreview(m_sg); //moved to starttransfer? + m_haveVideo = true; + return true; +} + +void videoDarwin :: setupCapture() +{ + if(stop()) { + SGSetChannelUsage(m_vc, 0); + SGSetChannelUsage(m_vc, seqGrabPreview); + SGUpdate(m_sg,0); + start(); + } +} + +void videoDarwin :: destroySeqGrabber() +{ + if (m_vc) { + if (::SGDisposeChannel(m_sg, m_vc)) { + error ("Unable to dispose a video channel"); + } + m_vc = NULL; + } + if (m_sg) { + if (::CloseComponent(m_sg)) { + error("Unable to dispose a sequence grabber component"); + } + m_sg = NULL; + if (m_srcGWorld) { + ::DisposeGWorld(m_srcGWorld); + m_srcGWorld = NULL; + } + } +} + +void videoDarwin :: resetSeqGrabber() +{ + OSErr anErr; + post ("starting reset"); + + destroySeqGrabber(); + initSeqGrabber(); +} + +///////////////////////////////////////////////////////// +// colorspaceMess +// +///////////////////////////////////////////////////////// +bool videoDarwin :: setColor(int format) +{ + m_colorspace = format; + if(stop()) { + resetSeqGrabber(); + start(); + } +} + + +///////////////////////////////////////////////////////// +// dialog +// +///////////////////////////////////////////////////////// +bool videoDarwin :: dialog(std::vectordlg) +{ + Rect newActiveVideoRect; + Rect curBounds, curVideoRect, newVideoRect; + ComponentResult err; + + // Get our current state - do i need this??? + err = SGGetChannelBounds (m_vc, &curBounds); + err = SGGetVideoRect (m_vc, &curVideoRect); + + // Pause + err = SGPause (m_sg, true); + + // Do the dialog thang + err = SGSettingsDialog( m_sg, m_vc, 0, nil, 0, nil, 0); + + // What happened? + err = SGGetVideoRect (m_vc, &newVideoRect); + err = SGGetSrcVideoBounds (m_vc, &newActiveVideoRect); + + err = SGPause (m_sg, false); + + return true; +} + +std::vectorvideoDarwin :: dialogs(void) { + std::vectorresult; + return result; +} + +bool videoDarwin::enumProperties(gem::Properties&readable, + gem::Properties&writeable) { + bool iidc=false; + gem::any typ; + + readable.clear(); + writeable.clear(); + + typ=1.; + if(m_vdig) { + ComponentDescription desc; + GetComponentInfo((Component)m_vdig, &desc, NULL, NULL, NULL); + + iidc=vdSubtypeIIDC == desc.componentSubType; + } +#define SETPROP(key, value) typ=value; readable.set(key, typ); writeable.set(key, typ) +#define SETRPROP(key, value) typ=value; readable.set(key, typ) +#define SETWPROP(key, value) typ=value; writeable.set(key, typ) + SETPROP("Hue", 1); + SETPROP("Sharpness", 1); + SETPROP("Saturation", 1); + SETPROP("Brightness", 1); + if(!iidc) { + SETPROP("Contrast", 1); + SETPROP("KeyColor", 1); + //SETPROP("ClipState", 1); + //SETPROP("ClipRng", 1); + //SETPROP("PLLFilterType", 1); + SETWPROP("MasterBlendLevel", 1); + //SETPROP("PlayThroughOnOff", 1); + //SETPROP("FieldPreference", 1); + SETPROP("BlackLevelValue", 1); + SETPROP("WhiteLevelValue", 1); + //SETPROP("Input", 1); + //SETPROP("InputStandard", 1); + } else { + SETWPROP("Gain", 1); + SETWPROP("Iris", 1); + SETWPROP("Shutter", 1); + SETWPROP("Exposure", 1); + SETWPROP("WhiteBalanceU", 1); + SETWPROP("WhiteBalanceV", 1); + SETWPROP("Gamma", 1); + SETWPROP("Temperature", 1); + SETWPROP("Zoom", 1); + SETWPROP("Focus", 1); + SETWPROP("Pan", 1); + SETWPROP("Tilt", 1); + SETWPROP("OpticalFilter", 1); + SETWPROP("EdgeEnhancement", 1); + } + return true; +} + +bool videoDarwin::setIIDCProperty(OSType specifier, double value) { + QTAtomContainer atomContainer; + QTAtom featureAtom; + VDIIDCFeatureSettings settings; + ComponentDescription desc; + ComponentResult result = paramErr; + + //IIDC stuff + result = VDIIDCGetFeaturesForSpecifier(m_vdig, specifier, &atomContainer); + if (noErr != result) { + return false; + } + + featureAtom = QTFindChildByIndex(atomContainer, kParentAtomIsContainer, + vdIIDCAtomTypeFeature, 1, NULL); + if (0 == featureAtom) return false;//error("featureAtom vdIIDCFeatureSaturation not found"); + + result = QTCopyAtomDataToPtr(atomContainer, + QTFindChildByID(atomContainer, featureAtom, + vdIIDCAtomTypeFeatureSettings, + vdIIDCAtomIDFeatureSettings, NULL), + true, sizeof(settings), &settings, NULL); + + settings.state.flags = (vdIIDCFeatureFlagOn | + vdIIDCFeatureFlagManual | + vdIIDCFeatureFlagRawControl); + + settings.state.value = value; + + result = QTSetAtomData(atomContainer, + QTFindChildByID(atomContainer, featureAtom, + vdIIDCAtomTypeFeatureSettings, + vdIIDCAtomIDFeatureSettings, NULL), + sizeof(settings), &settings); + + result = VDIIDCSetFeatures(m_vdig, atomContainer); + + return true; +} +inline unsigned short d2us(double x) +{ return (unsigned short)(65535.*((x > 1.f) ? 1.f : ( (x < 0.f) ? 0.f : x))); } +inline double us2d(unsigned short x) +{ static double factor=1./65535.; return (x*factor); } + +bool videoDarwin::applyProperties(gem::Properties&props) { + bool restart=false; + + bool iidc=false; + if(m_vdig) { + ComponentDescription desc; + GetComponentInfo((Component)m_vdig, &desc, NULL, NULL, NULL); + iidc=(vdSubtypeIIDC == desc.componentSubType); + } + + std::vectorkeys=props.keys(); + int i=0; + for(i=0; ikeys=props.keys(); + bool iidc=false; + if(m_vdig) { + ComponentDescription desc; + GetComponentInfo((Component)m_vdig, &desc, NULL, NULL, NULL); + iidc=(vdSubtypeIIDC == desc.componentSubType); + } + + int i=0; + for(i=0; i videoDarwin::enumerate() { + std::vector result; + OSErr anErr; + SGDeviceList devices; + + anErr = SGGetChannelDeviceList(m_vc, sgDeviceListIncludeInputs, &devices); + if(anErr!=noErr){ + error("could not get SG channnel Device List"); + }else{ + short deviceCount = (*devices)->count; + short deviceIndex = (*devices)->selectedIndex; + short inputIndex; + post("SG channnel Device List count %d index %d",deviceCount,deviceIndex); + int i; + m_devices.clear(); + for (i = 0; i < deviceCount; i++){ + m_devices.push_back(pascal2str((*devices)->entry[i].name)); + post("SG channnel Device List[%d] %s", i, m_devices[i].c_str()); + } + SGGetChannelDeviceAndInputNames(m_vc, NULL, NULL, &inputIndex); + + bool showInputsAsDevices = ((*devices)->entry[deviceIndex].flags) & sgDeviceNameFlagShowInputsAsDevices; + + SGDeviceInputList theSGInputList = ((SGDeviceName *)(&((*devices)->entry[deviceIndex])))->inputs; //fugly + + //we should have device names in big ass undocumented structs + //walk through the list + for (i = 0; i < inputIndex; i++){ + std::string input=pascal2str((*theSGInputList)->entry[i].name); + post("SG channnel Input Device List %d %s", + i, input.c_str()); + } + } + + result=m_devices; + return result; +} +#endif // HAVE_VIDEODARWIN diff --git a/src/Gem/plugins/videoDarwin/videoDarwin.h b/src/Gem/plugins/videoDarwin/videoDarwin.h new file mode 100644 index 0000000..710631b --- /dev/null +++ b/src/Gem/plugins/videoDarwin/videoDarwin.h @@ -0,0 +1,106 @@ +/*----------------------------------------------------------------- + +GEM - Graphics Environment for Multimedia + +Copyright (c) 2002 James Tittle & Chris Clepper +Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. + +Linux version by Miller Puckette. msp@ucsd.edu + +-----------------------------------------------------------------*/ + +#ifndef _INCLUDE_GEMPLUGIN__VIDEODARWIN_VIDEODARWIN_H_ +#define _INCLUDE_GEMPLUGIN__VIDEODARWIN_VIDEODARWIN_H_ + +#include "plugins/videoBase.h" + +#ifdef HAVE_CARBON +# include +#endif + +#ifdef HAVE_QUICKTIME +# include +#endif + +/*----------------------------------------------------------------- + ------------------------------------------------------------------- + CLASS + pix_video + + captures a video on Apple machines + + KEYWORDS + pix + + -----------------------------------------------------------------*/ +namespace gem { namespace plugins { +class GEM_EXPORT videoDarwin : public videoBase { + public: + ////////// + // Constructor + videoDarwin(void); + + ////////// + // Destructor + virtual ~videoDarwin(void); + + //////// + // open the video-device + virtual bool openDevice(gem::Properties&props); + virtual void closeDevice(void); + + ////////// + // Start up the video device + // [out] int - returns 0 if bad + bool startTransfer(void); + ////////// + // Stop the video device + // [out] int - returns 0 if bad + bool stopTransfer(void); + + ////////// + // get the next frame + virtual bool grabFrame(void); + ////////// + // Set the video dimensions + virtual bool setColor(int d); + virtual bool dialog(std::vectordlg); + virtual std::vectordialogs(void); + + virtual bool enumProperties(gem::Properties&readable, + gem::Properties&writeable); + virtual void setProperties(gem::Properties&props); + virtual void getProperties(gem::Properties&props); + + protected: + bool initSeqGrabber(void); + void resetSeqGrabber(void); + void destroySeqGrabber(void); + virtual void setupCapture(void); + + + + int m_newFrame; + SeqGrabComponent m_sg; // Sequence Grabber Component + SGChannel m_vc; // Video Channel + GWorldPtr m_srcGWorld; // Capture Destination + unsigned long m_rowBytes; // Row bytes in a row + long m_quality; + int m_colorspace; + + int m_inputDevice; + int m_inputDeviceChannel; + VideoDigitizerComponent m_vdig; //gotta have the vdig + DigitizerInfo m_vdigInfo; //the info about the VDIG + + virtual std::vectorenumerate(void); + std::vectorm_devices; + + bool setIIDCProperty(OSType specifier, double value); + bool applyProperties(gem::Properties&props); + }; +};}; + +#endif // for header file