summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indi/webcam/v4l1_pwc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indi/webcam/v4l1_pwc.cpp')
-rw-r--r--kstars/kstars/indi/webcam/v4l1_pwc.cpp563
1 files changed, 563 insertions, 0 deletions
diff --git a/kstars/kstars/indi/webcam/v4l1_pwc.cpp b/kstars/kstars/indi/webcam/v4l1_pwc.cpp
new file mode 100644
index 00000000..9f644885
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l1_pwc.cpp
@@ -0,0 +1,563 @@
+/*
+ Phlips webcam driver for V4L 1
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <iostream>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#include "ccvt.h"
+#include "pwc-ioctl.h"
+#include "v4l1_pwc.h"
+#include "../eventloop.h"
+
+#define ERRMSG_SIZ 1024
+
+extern int errno;
+using namespace std;
+
+V4L1_PWC::V4L1_PWC()
+{
+ frameRate=15;
+ fd=-1;
+ streamActive = true;
+
+ YBuf = NULL;
+ UBuf = NULL;
+ VBuf = NULL;
+ colorBuffer= NULL;
+ buffer_start=NULL;
+}
+
+V4L1_PWC::~V4L1_PWC()
+{
+
+}
+
+int V4L1_PWC::connectCam(const char * devpath, char *errmsg)
+{
+ options= (ioNoBlock|ioUseSelect|haveBrightness|haveContrast|haveColor);
+ struct pwc_probe probe;
+ bool IsPhilips = false;
+ frameRate=15;
+ fd=-1;
+ streamActive = true;
+ buffer_start=NULL;
+
+ if (-1 == (fd=open(devpath,
+ O_RDONLY | ((options & ioNoBlock) ? O_NONBLOCK : 0)))) {
+
+ strncpy(errmsg, strerror(errno), 1024);
+ cerr << strerror(errno);
+ return -1;
+ }
+
+ cerr << "Device opened" << endl;
+
+ if (fd != -1) {
+ if (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
+ cerr << "Error: ioctl (VIDIOCGCAP)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGCAP)", 1024);
+ return -1;
+ }
+ if (-1 == ioctl (fd, VIDIOCGWIN, &window)) {
+ cerr << "Error: ioctl (VIDIOCGWIN)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGWIN)", 1024);
+ return -1;
+ }
+ if (-1 == ioctl (fd, VIDIOCGPICT, &picture_format)) {
+ cerr << "Error: ioctl (VIDIOCGPICT)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGPICT)", 1024);
+ return -1;
+ }
+ init(0);
+ }
+
+ // Check to see if it's really a philips webcam
+ if (ioctl(fd, VIDIOCPWCPROBE, &probe) == 0)
+ {
+ if (!strcmp(capability.name,probe.name))
+ {
+ IsPhilips = true;
+ type_=probe.type;
+ }
+ }
+
+ if (IsPhilips)
+ cerr << "Philips webcam type " << type_ << " detected" << endl;
+ else
+ {
+ strncpy(errmsg, "No Philips webcam detected.", 1024);
+ return -1;
+ }
+
+ cerr << "initial size w:" << window.width << " -- h: " << window.height << endl;
+
+
+ mmapInit();
+
+ setWhiteBalanceMode(PWC_WB_AUTO, errmsg);
+ multiplicateur_=1;
+ skippedFrame_=0;
+ lastGain_=getGain();
+
+ cerr << "All successful, returning\n";
+ return fd;
+}
+
+void V4L1_PWC::checkSize(int & x, int & y)
+{
+ if (x>=capability.maxwidth && y >= capability.maxheight)
+ {
+ x=capability.maxwidth;
+ y=capability.maxheight;
+ } else if (x>=352 && y >=288 && type_<700) {
+ x=352;y=288;
+ } else if (x>=320 && y >= 240) {
+ x=320;y=240;
+ } else if (x>=176 && y >=144 && type_<700 ) {
+ x=176;y=144;
+ } else if (x>=160 && y >=120 ) {
+ x=160;y=120;
+ } else {
+ x=capability.minwidth;
+ y=capability.minheight;
+ }
+}
+
+bool V4L1_PWC::setSize(int x, int y)
+{
+
+ int oldX, oldY;
+ char msg[ERRMSG_SIZ];
+ checkSize(x,y);
+
+ oldX = window.width;
+ oldY = window.height;
+
+ window.width=x;
+ window.height=y;
+
+ if (ioctl (fd, VIDIOCSWIN, &window))
+ {
+ snprintf(msg, ERRMSG_SIZ, "ioctl(VIDIOCSWIN) %s", strerror(errno));
+ cerr << msg << endl;
+ window.width=oldX;
+ window.height=oldY;
+ return false;
+ }
+ ioctl (fd, VIDIOCGWIN, &window);
+
+ cerr << "New size is x=" << window.width << " " << "y=" << window.height <<endl;
+
+ allocBuffers();
+
+ return true;
+}
+
+int V4L1_PWC::saveSettings(char *errmsg)
+{
+ if (ioctl(fd, VIDIOCPWCSUSER)==-1)
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSUSER %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+void V4L1_PWC::restoreSettings()
+ {
+ ioctl(fd, VIDIOCPWCRUSER);
+ getPictureSettings();
+}
+
+void V4L1_PWC::restoreFactorySettings()
+{
+ ioctl(fd, VIDIOCPWCFACTORY);
+ getPictureSettings();
+}
+
+int V4L1_PWC::setGain(int val, char *errmsg)
+ {
+ if(-1==ioctl(fd, VIDIOCPWCSAGC, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSAGC %s", strerror(errno));
+ return -1;
+ }
+ else lastGain_=val;
+
+ cerr << "setGain "<<val<<endl;
+
+ return lastGain_;
+}
+
+int V4L1_PWC::getGain()
+{
+ int gain;
+ char msg[ERRMSG_SIZ];
+ static int cpt=0;
+ if ((cpt%4)==0)
+ {
+ if (-1==ioctl(fd, VIDIOCPWCGAGC, &gain))
+ {
+ //perror("VIDIOCPWCGAGC");
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGAGC %s", strerror(errno));
+ cerr << msg << endl;
+ gain=lastGain_;
+ } else
+ {
+ ++cpt;
+ lastGain_=gain;
+ }
+ } else
+ {
+ ++cpt;
+ gain=lastGain_;
+ }
+ //cerr << "get gain "<<gain<<endl;
+ if (gain < 0) gain*=-1;
+ return gain;
+}
+
+int V4L1_PWC::setExposure(int val, char *errmsg)
+ {
+ //cout << "set exposure "<<val<<"\n";
+
+ if (-1==ioctl(fd, VIDIOCPWCSSHUTTER, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSSHUTTER %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+void V4L1_PWC::setCompression(int val)
+{
+ ioctl(fd, VIDIOCPWCSCQUAL, &val);
+}
+
+int V4L1_PWC::getCompression()
+{
+ int gain;
+ ioctl(fd, VIDIOCPWCGCQUAL , &gain);
+ if (gain < 0) gain*=-1;
+ return gain;
+}
+
+int V4L1_PWC::setNoiseRemoval(int val, char *errmsg)
+{
+ if (-1 == ioctl(fd, VIDIOCPWCSDYNNOISE, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L1_PWC::getNoiseRemoval()
+{
+ int gain;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd, VIDIOCPWCGDYNNOISE , &gain))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ cout <<"get noise = "<<gain<<endl;
+ return gain;
+}
+
+int V4L1_PWC::setSharpness(int val, char *errmsg)
+ {
+ if (-1 == ioctl(fd, VIDIOCPWCSCONTOUR, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSCONTOUR %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L1_PWC::getSharpness()
+{
+ int gain;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd, VIDIOCPWCGCONTOUR, &gain))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGCONTOUR %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ cout <<"get sharpness = "<<gain<<endl;
+ return gain;
+}
+
+int V4L1_PWC::setBackLight(bool val, char *errmsg)
+{
+ static int on=1;
+ static int off=0;
+ if (-1 == ioctl(fd,VIDIOCPWCSBACKLIGHT, & val?&on:&off))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+bool V4L1_PWC::getBackLight()
+{
+ int val;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd,VIDIOCPWCGBACKLIGHT, & val))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ return val !=0;
+}
+
+int V4L1_PWC::setFlicker(bool val, char *errmsg)
+{
+ static int on=1;
+ static int off=0;
+ if (-1 == ioctl(fd,VIDIOCPWCSFLICKER, val?&on:&off))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSFLICKER %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+bool V4L1_PWC::getFlicker()
+{
+ int val;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd,VIDIOCPWCGFLICKER, & val))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGFLICKER %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ return val !=0;
+}
+
+void V4L1_PWC::setGama(int val)
+{
+ picture_format.whiteness=val;
+ setPictureSettings();
+}
+
+int V4L1_PWC::getGama()
+{
+ return picture_format.whiteness;
+}
+
+int V4L1_PWC::setFrameRate(int value, char *errmsg)
+ {
+ window.flags = (window.flags & ~PWC_FPS_MASK) | ((value << PWC_FPS_SHIFT) & PWC_FPS_MASK);
+ if (ioctl(fd, VIDIOCSWIN, &window))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "setFrameRate %s", strerror(errno));
+ return -1;
+ }
+
+ ioctl(fd, VIDIOCGWIN, &window);
+ frameRate = value;
+
+ return 0;
+ //emit exposureTime(multiplicateur_/(double)getFrameRate());
+}
+
+int V4L1_PWC::getFrameRate()
+{
+ return ((window.flags&PWC_FPS_FRMASK)>>PWC_FPS_SHIFT);
+}
+
+int V4L1_PWC::getWhiteBalance()
+{
+ char msg[ERRMSG_SIZ];
+ struct pwc_whitebalance tmp_whitebalance;
+ tmp_whitebalance.mode = tmp_whitebalance.manual_red = tmp_whitebalance.manual_blue = tmp_whitebalance.read_red = tmp_whitebalance.read_blue = PWC_WB_AUTO;
+
+ if (ioctl(fd, VIDIOCPWCGAWB, &tmp_whitebalance))
+ {
+ snprintf(msg, ERRMSG_SIZ, "getWhiteBalance %s", strerror(errno));
+ cerr << msg << endl;
+ }
+ else
+ {
+#if 0
+ cout << "mode="<<tmp_whitebalance.mode
+ <<" mr="<<tmp_whitebalance.manual_red
+ <<" mb="<<tmp_whitebalance.manual_blue
+ <<" ar="<<tmp_whitebalance.read_red
+ <<" ab="<<tmp_whitebalance.read_blue
+ <<endl;
+#endif
+ /* manual_red and manual_blue are garbage :-( */
+ whiteBalanceMode_=tmp_whitebalance.mode;
+ }
+
+ return whiteBalanceMode_;
+
+ /*switch(whiteBalanceMode_) {
+ case PWC_WB_INDOOR:
+ setProperty("WhiteBalanceMode","Indor");
+ break;
+ case PWC_WB_OUTDOOR:
+ setProperty("WhiteBalanceMode","Outdoor");
+ break;
+ case PWC_WB_FL:
+ setProperty("WhiteBalanceMode","Neon");
+ break;
+ case PWC_WB_MANUAL:
+ setProperty("WhiteBalanceMode","Manual");
+ whiteBalanceRed_=tmp_whitebalance.manual_red;
+ whiteBalanceBlue_=tmp_whitebalance.manual_blue;
+
+ break;
+ case PWC_WB_AUTO:
+ setProperty("WhiteBalanceMode","Auto");
+ whiteBalanceRed_=tmp_whitebalance.read_red;
+ whiteBalanceBlue_=tmp_whitebalance.read_blue;
+ break;
+ default:
+ setProperty("WhiteBalanceMode","???");
+ }
+
+ emit whiteBalanceModeChange(whiteBalanceMode_);
+
+ if (((whiteBalanceMode_ == PWC_WB_AUTO) && liveWhiteBalance_)
+ || whiteBalanceMode_ != PWC_WB_AUTO) {
+ setProperty("WhiteBalanceRed",whiteBalanceRed_);
+ emit whiteBalanceRedChange(whiteBalanceRed_);
+ setProperty("WhiteBalanceBlue",whiteBalanceBlue_);
+ emit whiteBalanceBlueChange(whiteBalanceBlue_);
+ if (guiBuild()) {
+ remoteCTRLWBred_->show();
+ remoteCTRLWBblue_->show();
+ }
+ } else {
+ if (guiBuild()) {
+ remoteCTRLWBred_->hide();
+ remoteCTRLWBblue_->hide();
+ }
+ }
+ }*/
+}
+
+int V4L1_PWC::setWhiteBalance(char *errmsg)
+{
+ struct pwc_whitebalance wb;
+ wb.mode=whiteBalanceMode_;
+ if (wb.mode == PWC_WB_MANUAL)
+ {
+ wb.manual_red=whiteBalanceRed_;
+ wb.manual_blue=whiteBalanceBlue_;
+ }
+
+ if (ioctl(fd, VIDIOCPWCSAWB, &wb))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "setWhiteBalance %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L1_PWC::setWhiteBalanceMode(int val, char *errmsg)
+ {
+ if (val == whiteBalanceMode_)
+ return whiteBalanceMode_;
+
+ if (val != PWC_WB_AUTO)
+ {
+ if ( val != PWC_WB_MANUAL)
+ {
+ whiteBalanceMode_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+ }
+
+ //whiteBalanceMode_=PWC_WB_AUTO;
+ whiteBalanceMode_= val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+ getWhiteBalance();
+ }
+
+ /*if (guiBuild()) {
+ if (val != PWC_WB_AUTO
+ || ( liveWhiteBalance_ && (val ==PWC_WB_AUTO))) {
+ remoteCTRLWBred_->show();
+ remoteCTRLWBblue_->show();
+ } else {
+ remoteCTRLWBred_->hide();
+ remoteCTRLWBblue_->hide();
+ }
+ }*/
+
+ whiteBalanceMode_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+ getWhiteBalance();
+
+ return 0;
+}
+
+int V4L1_PWC::setWhiteBalanceRed(int val, char *errmsg)
+{
+ whiteBalanceMode_ = PWC_WB_MANUAL;
+ whiteBalanceRed_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+
+ return 0;
+}
+
+int V4L1_PWC::setWhiteBalanceBlue(int val, char *errmsg)
+{
+ whiteBalanceMode_ = PWC_WB_MANUAL;
+ whiteBalanceBlue_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+
+ return 0;
+}
+