aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kvilib/CMakeLists.txt9
-rw-r--r--src/kvilib/ext/avdevice/bayer.cpp144
-rw-r--r--src/kvilib/ext/avdevice/bayer.h56
-rw-r--r--src/kvilib/ext/avdevice/dummyvideodevice.cpp222
-rw-r--r--src/kvilib/ext/avdevice/dummyvideodevice.h96
-rw-r--r--src/kvilib/ext/avdevice/kopete_export.h4
-rw-r--r--src/kvilib/ext/avdevice/sonix_compress.cpp206
-rw-r--r--src/kvilib/ext/avdevice/sonix_compress.h34
-rw-r--r--src/kvilib/ext/avdevice/videodevice.cpp2976
-rw-r--r--src/kvilib/ext/avdevice/videodevice.h374
-rw-r--r--src/kvilib/ext/avdevice/videodevicemodelpool.cpp94
-rw-r--r--src/kvilib/ext/avdevice/videodevicemodelpool.h79
-rw-r--r--src/kvilib/ext/avdevice/videodevicepool.cpp940
-rw-r--r--src/kvilib/ext/avdevice/videodevicepool.h175
-rw-r--r--src/kvilib/ext/avdevice/videodevicevector.cpp88
-rw-r--r--src/kvilib/ext/avdevice/videodevicevector.h89
-rw-r--r--src/kvilib/ext/avdevice/videoinput.cpp198
-rw-r--r--src/kvilib/ext/avdevice/videoinput.h111
-rw-r--r--src/kvirc/kernel/kvi_options.cpp5
-rw-r--r--src/kvirc/kernel/kvi_options.h5
-rw-r--r--src/modules/dcc/CMakeLists.txt2
-rw-r--r--src/modules/dcc/broker.cpp70
-rw-r--r--src/modules/dcc/broker.h4
-rw-r--r--src/modules/dcc/codec.cpp67
-rw-r--r--src/modules/dcc/codec.h26
-rw-r--r--src/modules/dcc/libkvidcc.cpp65
-rw-r--r--src/modules/dcc/requests.cpp79
-rw-r--r--src/modules/dcc/video.cpp686
-rw-r--r--src/modules/dcc/video.h155
29 files changed, 7055 insertions, 4 deletions
diff --git a/src/kvilib/CMakeLists.txt b/src/kvilib/CMakeLists.txt
index 97dcd5881..8a9e97e32 100644
--- a/src/kvilib/CMakeLists.txt
+++ b/src/kvilib/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(kvilib_MOC_HDRS
ext/kvi_crypt.h
ext/kvi_regusersdb.h
ext/kvi_sharedfiles.h
+ ext/avdevice/videodevicepool.h
irc/kvi_ircuserdb.h
net/kvi_dns.h
net/kvi_http.h
@@ -76,6 +77,14 @@ SET(kvilib_SRCS
ext/kvi_regusersdb.cpp
ext/kvi_sharedfiles.cpp
ext/kvi_stringconversion.cpp
+ ext/avdevice/videodevice.cpp
+ ext/avdevice/videoinput.cpp
+ ext/avdevice/dummyvideodevice.cpp
+ ext/avdevice/videodevicevector.cpp
+ ext/avdevice/videodevicepool.cpp
+ ext/avdevice/videodevicemodelpool.cpp
+ ext/avdevice/bayer.cpp
+ ext/avdevice/sonix_compress.cpp
file/kvi_file.cpp
file/kvi_fileutils.cpp
file/kvi_packagefile.cpp
diff --git a/src/kvilib/ext/avdevice/bayer.cpp b/src/kvilib/ext/avdevice/bayer.cpp
new file mode 100644
index 000000000..11183a4ff
--- /dev/null
+++ b/src/kvilib/ext/avdevice/bayer.cpp
@@ -0,0 +1,144 @@
+//=============================================================================
+//
+// File : bayer.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ * BAYER2RGB24 ROUTINE TAKEN FROM:
+ *
+ * Sonix SN9C101 based webcam basic I/F routines
+ * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
+{
+ long int i;
+ unsigned char *rawpt, *scanpt;
+ long int size;
+
+ rawpt = src;
+ scanpt = dst;
+ size = WIDTH*HEIGHT;
+
+ for ( i = 0; i < size; i++ )
+ {
+ if ( (i/WIDTH) % 2 == 0 )
+ {
+ if ( (i % 2) == 0 )
+ {
+ // B
+ if ( (i > WIDTH) && ((i % WIDTH) > 0) )
+ {
+ *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; // R
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt+WIDTH)+*(rawpt-WIDTH))/4; // G
+ *scanpt++ = *rawpt; // B
+ }
+ else
+ {
+ // first line or left column
+ *scanpt++ = *(rawpt+WIDTH+1); // R
+ *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; // G
+ *scanpt++ = *rawpt; // B
+ }
+ }
+ else
+ {
+ // (B)G
+ if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
+ {
+ *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; // R
+ *scanpt++ = *rawpt; // G
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; // B
+ }
+ else
+ {
+ // first line or right column
+ *scanpt++ = *(rawpt+WIDTH); // R
+ *scanpt++ = *rawpt; // G
+ *scanpt++ = *(rawpt-1); // B
+ }
+ }
+ }
+ else
+ {
+ if ( (i % 2) == 0 )
+ {
+ // G(R)
+ if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
+ {
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; // R
+ *scanpt++ = *rawpt; // G
+ *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; // B
+ }
+ else
+ {
+ // bottom line or left column
+ *scanpt++ = *(rawpt+1); /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = *(rawpt-WIDTH); /* B */
+ }
+ }
+ else
+ {
+ // R
+ if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
+ {
+ *scanpt++ = *rawpt; // R
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; // G
+ *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; // B
+ }
+ else
+ {
+ // bottom line or right column
+ *scanpt++ = *rawpt; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
+ *scanpt++ = *(rawpt-WIDTH-1); /* B */
+ }
+ }
+ }
+ rawpt++;
+ }
+}
+
diff --git a/src/kvilib/ext/avdevice/bayer.h b/src/kvilib/ext/avdevice/bayer.h
new file mode 100644
index 000000000..6df2f679f
--- /dev/null
+++ b/src/kvilib/ext/avdevice/bayer.h
@@ -0,0 +1,56 @@
+//=============================================================================
+//
+// File : bayer.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ * BAYER2RGB24 ROUTINE TAKEN FROM:
+ *
+ * Sonix SN9C101 based webcam basic I/F routines
+ * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+void bayer2rgb24 (unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT);
diff --git a/src/kvilib/ext/avdevice/dummyvideodevice.cpp b/src/kvilib/ext/avdevice/dummyvideodevice.cpp
new file mode 100644
index 000000000..6ad36ce19
--- /dev/null
+++ b/src/kvilib/ext/avdevice/dummyvideodevice.cpp
@@ -0,0 +1,222 @@
+//=============================================================================
+//
+// File : dummyvideodevice.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ dummyvideodevice.cpp - Dummy Video Device
+
+ Copyright (c) 2009 by Alan Jones <skyphyr@gmail.com>
+
+ Kopete (c) 2002-2009 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ *************************************************************************
+*/
+
+#include "dummyvideodevice.h"
+#include "videoinput.h"
+
+namespace Kopete {
+
+namespace AV {
+
+DummyVideoDevice::DummyVideoDevice()
+ {
+ //need to set a bunch of defaults for members
+ m_pixelformat = PIXELFORMAT_RGB32;
+ m_driver=VIDEODEV_DRIVER_NONE;
+ m_input.append(VideoInput());
+ minwidth = 160;
+ maxwidth = 1280;
+ minheight = 120;
+ maxheight = 960;
+ //let's be opened by default seeing this is a fallback
+ opened = true;
+ setSize(320, 240);
+ }
+
+int DummyVideoDevice::open()
+ {
+ //wow - we always succeed in opening our dummy device
+ opened = true;
+ return EXIT_SUCCESS;
+ }
+
+bool DummyVideoDevice::isOpen()
+ {
+ //we'll track it just incase there is situations where it's expected not to be open
+ return opened;
+ }
+
+int DummyVideoDevice::checkDevice()
+ {
+ //again this is just incase anything ever relies on it failing when closed
+ if(isOpen())
+ {
+ //need to check which, if any, of these need to be enabled for this to function properly
+ m_videocapture=false;
+ m_videochromakey=false;
+ m_videoscale=false;
+ m_videooverlay=false;
+ m_videoread=false;
+ m_videoasyncio=false;
+ m_videostream=false;
+
+ m_driver=VIDEODEV_DRIVER_NONE;
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+int DummyVideoDevice::initDevice()
+ {
+ //again this is just incase anything ever relies on it failing when closed
+ if(isOpen())
+ {
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+int DummyVideoDevice::setSize( int newwidth, int newheight)
+ {
+ if (isOpen())
+ {
+ if(newwidth > maxwidth ) newwidth = maxwidth;
+ if(newheight > maxheight) newheight = maxheight;
+ if(newwidth < minwidth ) newwidth = minwidth;
+ if(newheight < minheight) newheight = minheight;
+
+ currentwidth = newwidth;
+ currentheight = newheight;
+
+ m_currentbuffer.width = currentwidth;
+ m_currentbuffer.height = currentheight;
+ m_currentbuffer.pixelformat = m_pixelformat;
+
+ //let's fill the buffer up with something
+ //TODO: replace this with an .svg that says there is no camera available
+ m_currentbuffer.data.resize(currentwidth * currentheight * 4);
+ for (int i=0; i<m_currentbuffer.data.size(); i++)
+ {
+ m_currentbuffer.data[i] = 255;
+ }
+
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+pixel_format DummyVideoDevice::setPixelFormat(pixel_format newformat)
+ {
+ pixel_format ret = PIXELFORMAT_NONE;
+
+ if (newformat == PIXELFORMAT_RGB32)
+ {
+ m_pixelformat = newformat;
+ ret = m_pixelformat;
+ }
+
+ return ret;
+ }
+
+int DummyVideoDevice::startCapturing()
+ {
+ //again this is just incase anything ever relies on it failing when closed
+ if(isOpen())
+ {
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+int DummyVideoDevice::getFrame()
+ {
+ //again this is just incase anything ever relies on it failing when closed
+ if(isOpen())
+ {
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+int DummyVideoDevice::getFrame(imagebuffer *imgbuffer)
+ {
+ if(imgbuffer)
+ {
+ imgbuffer->height = m_currentbuffer.height;
+ imgbuffer->width = m_currentbuffer.width;
+ imgbuffer->pixelformat = m_currentbuffer.pixelformat;
+ imgbuffer->data = m_currentbuffer.data;
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+int DummyVideoDevice::getImage(QImage *qimage)
+ {
+ // do NOT delete qimage here, as it is received as a parameter
+ if (qimage->width() != width() || qimage->height() != height())
+ *qimage = QImage(width(), height(), QImage::Format_RGB32);
+
+ uchar *bits=qimage->bits();
+ memcpy(bits,&m_currentbuffer.data[0], m_currentbuffer.data.size());
+
+ return EXIT_SUCCESS;
+ }
+
+int DummyVideoDevice::stopCapturing()
+ {
+ //again this is just incase anything ever relies on it failing when closed
+ if(isOpen())
+ {
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ }
+
+int DummyVideoDevice::close()
+ {
+ //we always manage to close it too - amazing :)
+ opened = false;
+ return EXIT_SUCCESS;
+ }
+
+}
+
+}
diff --git a/src/kvilib/ext/avdevice/dummyvideodevice.h b/src/kvilib/ext/avdevice/dummyvideodevice.h
new file mode 100644
index 000000000..96498b661
--- /dev/null
+++ b/src/kvilib/ext/avdevice/dummyvideodevice.h
@@ -0,0 +1,96 @@
+//=============================================================================
+//
+// File : dummyvideodevice.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ dummyvideodevice.h - Kopete Dummy Video Device
+
+ Copyright (c) 2009 by Alan Jones <skyphyr@gmail.com>
+
+ Kopete (c) 2002-2009 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ *************************************************************************
+*/
+
+#ifndef KOPETE_AVDUMMYVIDEODEVICE_H
+#define KOPETE_AVDUMMYVIDEODEVICE_H
+
+#include "videodevice.h"
+
+namespace Kopete {
+
+namespace AV {
+
+/**
+@author Kopete Developers
+*/
+
+class DummyVideoDevice : public VideoDevice
+{
+
+public:
+ DummyVideoDevice();
+ virtual ~DummyVideoDevice() {}
+
+ virtual int open();
+ virtual bool isOpen();
+ virtual int checkDevice();
+ virtual int initDevice();
+
+ virtual int setSize( int newwidth, int newheight);
+
+ virtual pixel_format setPixelFormat(pixel_format newformat);
+
+ virtual int startCapturing();
+ virtual int getFrame();
+ virtual int getFrame(imagebuffer *imgbuffer);
+ virtual int getImage(QImage *qimage);
+ virtual int stopCapturing();
+ virtual int close();
+
+
+private:
+ bool opened;
+};
+
+}
+
+}
+
+#endif
diff --git a/src/kvilib/ext/avdevice/kopete_export.h b/src/kvilib/ext/avdevice/kopete_export.h
new file mode 100644
index 000000000..029e74dc3
--- /dev/null
+++ b/src/kvilib/ext/avdevice/kopete_export.h
@@ -0,0 +1,4 @@
+#define KOPETE_EXPORT
+
+#define __linux__ 1
+#define ENABLE_AV \ No newline at end of file
diff --git a/src/kvilib/ext/avdevice/sonix_compress.cpp b/src/kvilib/ext/avdevice/sonix_compress.cpp
new file mode 100644
index 000000000..653cb951b
--- /dev/null
+++ b/src/kvilib/ext/avdevice/sonix_compress.cpp
@@ -0,0 +1,206 @@
+//=============================================================================
+//
+// File : sonix_compress.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original file had no copyright header.
+//=============================================================================
+
+#include "sonix_compress.h"
+
+#define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
+
+typedef struct {
+ int is_abs;
+ int len;
+ int val;
+ int unk;
+} code_table_t;
+
+
+/* local storage */
+static code_table_t table[256];
+static int init_done = 0;
+
+/* global variable */
+int sonix_unknown = 0;
+
+/*
+ sonix_decompress_init
+ =====================
+ pre-calculates a locally stored table for efficient huffman-decoding.
+
+ Each entry at index x in the table represents the codeword
+ present at the MSB of byte x.
+
+*/
+void sonix_decompress_init(void)
+{
+ int i;
+ int is_abs, val, len, unk;
+
+ for (i = 0; i < 256; i++) {
+ is_abs = 0;
+ val = 0;
+ len = 0;
+ unk = 0;
+ if ((i & 0x80) == 0) {
+ /* code 0 */
+ val = 0;
+ len = 1;
+ }
+ else if ((i & 0xE0) == 0x80) {
+ /* code 100 */
+ val = +4;
+ len = 3;
+ }
+ else if ((i & 0xE0) == 0xA0) {
+ /* code 101 */
+ val = -4;
+ len = 3;
+ }
+ else if ((i & 0xF0) == 0xD0) {
+ /* code 1101 */
+ val = +11;
+ len = 4;
+ }
+ else if ((i & 0xF0) == 0xF0) {
+ /* code 1111 */
+ val = -11;
+ len = 4;
+ }
+ else if ((i & 0xF8) == 0xC8) {
+ /* code 11001 */
+ val = +20;
+ len = 5;
+ }
+ else if ((i & 0xFC) == 0xC0) {
+ /* code 110000 */
+ val = -20;
+ len = 6;
+ }
+ else if ((i & 0xFC) == 0xC4) {
+ /* code 110001xx: unknown */
+ val = 0;
+ len = 8;
+ unk = 1;
+ }
+ else if ((i & 0xF0) == 0xE0) {
+ /* code 1110xxxx */
+ is_abs = 1;
+ val = (i & 0x0F) << 4;
+ len = 8;
+ }
+ table[i].is_abs = is_abs;
+ table[i].val = val;
+ table[i].len = len;
+ table[i].unk = unk;
+ }
+
+ sonix_unknown = 0;
+ init_done = 1;
+}
+
+
+/*
+ sonix_decompress
+ ================
+ decompresses an image encoded by a SN9C101 camera controller chip.
+
+ IN width
+ height
+ inp pointer to compressed frame (with header already stripped)
+ OUT outp pointer to decompressed frame
+
+ Returns 0 if the operation was successful.
+ Returns <0 if operation failed.
+
+*/
+int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
+{
+ int row, col;
+ int val;
+ int bitpos;
+ unsigned char code;
+ unsigned char *addr;
+
+ if (!init_done) {
+ /* do sonix_decompress_init first! */
+ return -1;
+ }
+
+ bitpos = 0;
+ for (row = 0; row < height; row++) {
+
+ col = 0;
+
+ /* first two pixels in first two rows are stored as raw 8-bit */
+ if (row < 2) {
+ addr = inp + (bitpos >> 3);
+ code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
+ bitpos += 8;
+ *outp++ = code;
+
+ addr = inp + (bitpos >> 3);
+ code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
+ bitpos += 8;
+ *outp++ = code;
+
+ col += 2;
+ }
+
+ while (col < width) {
+ /* get bitcode from bitstream */
+ addr = inp + (bitpos >> 3);
+ code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
+
+ /* update bit position */
+ bitpos += table[code].len;
+
+ /* update code statistics */
+ sonix_unknown += table[code].unk;
+
+ /* calculate pixel value */
+ val = table[code].val;
+ if (!table[code].is_abs) {
+ /* value is relative to top and left pixel */
+ if (col < 2) {
+ /* left column: relative to top pixel */
+ val += outp[-2*width];
+ }
+ else if (row < 2) {
+ /* top row: relative to left pixel */
+ val += outp[-2];
+ }
+ else {
+ /* main area: average of left pixel and top pixel */
+ val += (outp[-2] + outp[-2*width]) / 2;
+ }
+ }
+
+ /* store pixel */
+ *outp++ = CLAMP(val);
+ col++;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/kvilib/ext/avdevice/sonix_compress.h b/src/kvilib/ext/avdevice/sonix_compress.h
new file mode 100644
index 000000000..70058d657
--- /dev/null
+++ b/src/kvilib/ext/avdevice/sonix_compress.h
@@ -0,0 +1,34 @@
+//=============================================================================
+//
+// File : sonix_compress.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original file had no copyright header.
+//=============================================================================
+
+// Call this function first (just once is needed), before calling sonix_decompress
+void sonix_decompress_init(void);
+
+// decompresses data at inp until a full image of widthxheight has been written to outp
+int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp);
+
+// counter to detect presence of currently unknown huffman codes
+extern int sonix_unknown;
diff --git a/src/kvilib/ext/avdevice/videodevice.cpp b/src/kvilib/ext/avdevice/videodevice.cpp
new file mode 100644
index 000000000..7116e2954
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevice.cpp
@@ -0,0 +1,2976 @@
+//=============================================================================
+//
+// File : videodevice.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevice.cpp - Kopete Video Device Low-level Support
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#define ENABLE_AV
+
+#include <cstdlib>
+#include <cerrno>
+#include <cstring>
+
+#include <kdebug.h>
+
+#include "videoinput.h"
+#include "videodevice.h"
+
+#include "bayer.h"
+#include "sonix_compress.h"
+
+#define CLEAR(x) memset (&(x), 0, sizeof (x))
+
+namespace Kopete {
+
+namespace AV {
+
+VideoDevice::VideoDevice()
+{
+// kDebug() << "libkopete (avdevice): VideoDevice() called";
+ descriptor = -1;
+ m_streambuffers = 0;
+ m_current_input = 0;
+// kDebug() << "libkopete (avdevice): VideoDevice() exited successfuly";
+}
+
+
+VideoDevice::~VideoDevice()
+{
+}
+
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+
+void VideoDevice::enumerateControls (void)
+{
+// -----------------------------------------------------------------------------------------------------------------
+// This must turn up to be a proper method to check for controls' existence.
+ CLEAR (queryctrl);
+// v4l2_queryctrl may zero the .id in some cases, even if the IOCTL returns EXIT_SUCCESS (tested with a bttv card, when testing for V4L2_CID_AUDIO_VOLUME).
+// As of 6th Aug 2007, according to the V4L2 specification version 0.21, this behavior is undocumented, and the example 1-8 code found at
+// http://www.linuxtv.org/downloads/video4linux/API/V4L2_API/spec/x519.htm fails because of this behavior with a bttv card.
+
+ int currentid = V4L2_CID_BASE;
+
+kDebug() << "Checking CID controls";
+
+ for (currentid = V4L2_CID_BASE; currentid < V4L2_CID_LASTP1; currentid++)
+//for (queryctrl.id = 9963776; queryctrl.id < 9963800; queryctrl.id++)
+ {
+ queryctrl.id = currentid;
+ if (0 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ continue;
+
+kDebug() << " Control: " << QString::fromLocal8Bit((const char*)queryctrl.name) << " Values from " << queryctrl.minimum << " to " << queryctrl.maximum << " with steps of " << queryctrl.step << ". Default: " << queryctrl.default_value;
+
+// switch (queryctrl.type)
+// {
+// case V4L2_CTRL_TYPE_INTEGER :
+// }
+ if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+ enumerateMenu ();
+ }
+ else
+ {
+ if (errno == EINVAL)
+ continue;
+
+ perror ("VIDIOC_QUERYCTRL");
+// exit (EXIT_FAILURE);
+ }
+ }
+
+kDebug() << "Checking CID private controls";
+
+ for (currentid = V4L2_CID_PRIVATE_BASE;; currentid++)
+ {
+ queryctrl.id = currentid;
+ if ( 0 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ continue;
+
+kDebug() << " Control: " << QString::fromLocal8Bit((const char*)queryctrl.name) << " Values from " << queryctrl.minimum << " to " << queryctrl.maximum << " with steps of " << queryctrl.step << ". Default: " << queryctrl.default_value;
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+ enumerateMenu ();
+ }
+ else
+ {
+ if (errno == EINVAL)
+ break;
+
+ perror ("VIDIOC_QUERYCTRL");
+// exit (EXIT_FAILURE);
+ }
+ }
+}
+
+void VideoDevice::enumerateMenu (void)
+{
+ kDebug() << " Menu items:";
+
+ memset (&querymenu, 0, sizeof (querymenu));
+ querymenu.id = queryctrl.id;
+
+ for (querymenu.index = queryctrl.minimum; querymenu.index <= (unsigned int) queryctrl.maximum; ++querymenu.index)
+ {
+ if (0 == xioctl (VIDIOC_QUERYMENU, &querymenu))
+ {
+ kDebug() << " " << QString::fromLocal8Bit((const char*)querymenu.name);
+ }
+ else
+ {
+ perror ("VIDIOC_QUERYMENU");
+ exit (EXIT_FAILURE);
+ }
+ }
+}
+#endif
+
+/*!
+ \fn VideoDevice::xioctl(int fd, int request, void *arg)
+ */
+int VideoDevice::xioctl(int request, void *arg)
+{
+ int r;
+
+#ifdef HAVE_LIBV4L2
+ do r = v4l2_ioctl (descriptor, request, arg);
+#else
+ do r = ioctl (descriptor, request, arg);
+#endif
+ while (-1 == r && EINTR == errno);
+ return r;
+}
+
+/*!
+ \fn VideoDevice::errnoReturn(const char* s)
+ */
+int VideoDevice::errnoReturn(const char* s)
+{
+ /// @todo implement me
+ fprintf (stderr, "%s error %d, %s\n",s, errno, strerror (errno));
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevice::setFileName(QString name)
+ */
+int VideoDevice::setFileName(QString filename)
+{
+ /// @todo implement me
+ full_filename=filename;
+ return EXIT_SUCCESS;
+}
+
+/*!
+ \fn VideoDevice::open()
+ */
+int VideoDevice::open()
+{
+ /// @todo implement me
+
+ kDebug() << "called";
+ if(-1 != descriptor)
+ {
+ kDebug() << "Device is already open";
+ return EXIT_SUCCESS;
+ }
+#ifdef HAVE_LIBV4L2
+ descriptor = ::v4l2_open (QFile::encodeName(full_filename), O_RDWR, 0);
+#else
+ descriptor = ::open (QFile::encodeName(full_filename), O_RDWR, 0);
+#endif
+ if(isOpen())
+ {
+ kDebug() << "File " << full_filename << " was opened successfuly";
+ if(EXIT_FAILURE==checkDevice())
+ {
+ kDebug() << "File " << full_filename << " could not be opened";
+ close();
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ kDebug() << "Unable to open file " << full_filename << "Err: "<< errno;
+ return EXIT_FAILURE;
+ }
+
+ initDevice();
+ selectInput(m_current_input);
+ kDebug() << "exited successfuly";
+ return EXIT_SUCCESS;
+}
+
+bool VideoDevice::isOpen()
+{
+ if(-1 == descriptor)
+ {
+// kDebug() << "VideoDevice::isOpen() File is not open";
+ return false;
+ }
+// kDebug() << "VideoDevice::isOpen() File is open";
+ return true;
+}
+
+int VideoDevice::checkDevice()
+{
+ kDebug() << "checkDevice() called.";
+ if(isOpen())
+ {
+ m_videocapture=false;
+ m_videochromakey=false;
+ m_videoscale=false;
+ m_videooverlay=false;
+ m_videoread=false;
+ m_videoasyncio=false;
+ m_videostream=false;
+
+ m_driver=VIDEODEV_DRIVER_NONE;
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+
+ CLEAR(V4L2_capabilities);
+
+ if (-1 != xioctl (VIDIOC_QUERYCAP, &V4L2_capabilities))
+ {
+ if (!(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ {
+ kDebug() << "checkDevice(): " << full_filename << " is not a video capture device.";
+ m_driver = VIDEODEV_DRIVER_NONE;
+ return EXIT_FAILURE;
+ }
+ m_videocapture=true;
+ kDebug() << "checkDevice(): " << full_filename << " is a V4L2 device.";
+ m_driver = VIDEODEV_DRIVER_V4L2;
+ m_model=QString::fromLocal8Bit((const char*)V4L2_capabilities.card);
+
+
+// Detect maximum and minimum resolution supported by the V4L2 device. VIDIOC_ENUM_FRAMESIZES is still experimental.
+ CLEAR (fmt);
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == xioctl (VIDIOC_G_FMT, &fmt))
+ {
+ kDebug() << "VIDIOC_G_FMT failed (" << errno << ").";
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = 32767;
+ fmt.fmt.pix.height = 32767;
+ fmt.fmt.pix.field = V4L2_FIELD_ANY;
+ if (-1 == xioctl (VIDIOC_S_FMT, &fmt))
+ {
+ kDebug() << "Detecting maximum size with VIDIOC_S_FMT failed (" << errno << ").Returned maxwidth: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ // Note VIDIOC_S_FMT may change width and height.
+ }
+ else
+ {
+ maxwidth = fmt.fmt.pix.width;
+ maxheight = fmt.fmt.pix.height;
+ }
+ if (-1 == xioctl (VIDIOC_G_FMT, &fmt))
+ {
+ kDebug() << "VIDIOC_G_FMT failed (" << errno << ").";
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = 1;
+ fmt.fmt.pix.height = 1;
+ fmt.fmt.pix.field = V4L2_FIELD_ANY;
+ if (-1 == xioctl (VIDIOC_S_FMT, &fmt))
+ {
+ kDebug() << "Detecting minimum size with VIDIOC_S_FMT failed (" << errno << ").Returned maxwidth: " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ // Note VIDIOC_S_FMT may change width and height.
+ }
+ else
+ {
+ minwidth = fmt.fmt.pix.width;
+ minheight = fmt.fmt.pix.height;
+ }
+
+// Buggy driver paranoia
+/* min = fmt.fmt.pix.width * 2;
+ if (fmt.fmt.pix.bytesperline < min)
+ fmt.fmt.pix.bytesperline = min;
+ min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
+ if (fmt.fmt.pix.sizeimage < min)
+ fmt.fmt.pix.sizeimage = min;
+ m_buffer_size=fmt.fmt.pix.sizeimage ;*/
+
+ int inputisok=EXIT_SUCCESS;
+ m_input.clear();
+ for(unsigned int loop=0; inputisok==EXIT_SUCCESS; loop++)
+ {
+ struct v4l2_input videoinput;
+ CLEAR(videoinput);
+ videoinput.index = loop;
+ inputisok=xioctl(VIDIOC_ENUMINPUT, &videoinput);
+ if(inputisok==EXIT_SUCCESS)
+ {
+ VideoInput tempinput;
+ tempinput.name = QString::fromLocal8Bit((const char*)videoinput.name);
+ tempinput.hastuner = videoinput.type & V4L2_INPUT_TYPE_TUNER;
+detectSignalStandards();
+ tempinput.m_standards = videoinput.std;
+ m_input.push_back(tempinput);
+ kDebug() << "Input " << loop << ": " << tempinput.name << " (tuner: " << ((videoinput.type & V4L2_INPUT_TYPE_TUNER) != 0) << ")";
+ if((videoinput.type & V4L2_INPUT_TYPE_TUNER) != 0)
+ {
+// _tunerForInput[name] = desc.tuner;
+// _isTuner = true;
+ }
+ else
+ {
+// _tunerForInput[name] = -1;
+ }
+ }
+ }
+ }
+ else
+ {
+// V4L-only drivers should return an EINVAL in errno to indicate they cannot handle V4L2 calls. Not every driver is compliant, so
+// it will try the V4L api even if the error code is different than expected.
+ kDebug() << "checkDevice(): " << full_filename << " is not a V4L2 device.";
+ }
+
+#endif
+
+ CLEAR(V4L_capabilities);
+
+ if(m_driver==VIDEODEV_DRIVER_NONE)
+ {
+ kDebug() << "checkDevice(): " << full_filename << " Trying V4L API.";
+ if (-1 == xioctl (VIDIOCGCAP, &V4L_capabilities))
+ {
+ perror ("ioctl (VIDIOCGCAP)");
+ m_driver = VIDEODEV_DRIVER_NONE;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ kDebug() << full_filename << " is a V4L device.";
+ m_driver = VIDEODEV_DRIVER_V4L;
+ m_model=QString::fromLocal8Bit((const char*)V4L_capabilities.name);
+ if(V4L_capabilities.type & VID_TYPE_CAPTURE)
+ m_videocapture=true;
+ if(V4L_capabilities.type & VID_TYPE_CHROMAKEY)
+ m_videochromakey=true;
+ if(V4L_capabilities.type & VID_TYPE_SCALES)
+ m_videoscale=true;
+ if(V4L_capabilities.type & VID_TYPE_OVERLAY)
+ m_videooverlay=true;
+// kDebug() << "libkopete (avdevice): Inputs : " << V4L_capabilities.channels;
+// kDebug() << "libkopete (avdevice): Audios : " << V4L_capabilities.audios;
+ minwidth = V4L_capabilities.minwidth;
+ maxwidth = V4L_capabilities.maxwidth;
+ minheight = V4L_capabilities.minheight;
+ maxheight = V4L_capabilities.maxheight;
+
+
+ int inputisok=EXIT_SUCCESS;
+ m_input.clear();
+ for(int loop=0; loop < V4L_capabilities.channels; loop++)
+ {
+ struct video_channel videoinput;
+ CLEAR(videoinput);
+ videoinput.channel = loop;
+ videoinput.norm = 1;
+ inputisok=xioctl(VIDIOCGCHAN, &videoinput);
+ if(inputisok==EXIT_SUCCESS)
+ {
+ VideoInput tempinput;
+ tempinput.name = QString::fromLocal8Bit((const char*)videoinput.name);
+ tempinput.hastuner=videoinput.flags & VIDEO_VC_TUNER;
+// TODO: The routine to detect the appropriate video standards for V4L must be placed here
+ m_input.push_back(tempinput);
+// kDebug() << "libkopete (avdevice): Input " << loop << ": " << tempinput.name << " (tuner: " << ((videoinput.flags & VIDEO_VC_TUNER) != 0) << ")";
+/* if((input.type & V4L2_INPUT_TYPE_TUNER) != 0)
+ {
+// _tunerForInput[name] = desc.tuner;
+// _isTuner = true;
+ }
+ else
+ {
+// _tunerForInput[name] = -1;
+ }
+*/ }
+ }
+
+ }
+ }
+#endif
+ m_name=m_model; // Take care about changing the name to be different from the model itself...
+
+ detectPixelFormats();
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ enumerateControls();
+#endif
+// TODO: Now we must execute the proper initialization according to the type of the driver.
+ kDebug() << "checkDevice() exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+
+/*!
+ \fn VideoDevice::showDeviceCapabilities()
+ */
+int VideoDevice::showDeviceCapabilities()
+{
+ kDebug() << "showDeviceCapabilities() called.";
+ if(isOpen())
+ {
+/* kDebug() << "libkopete (avdevice): Driver: " << (const char*)V4L2_capabilities.driver << " "
+ << ((V4L2_capabilities.version>>16) & 0xFF) << "."
+ << ((V4L2_capabilities.version>> 8) & 0xFF) << "."
+ << ((V4L2_capabilities.version ) & 0xFF) << endl;
+ kDebug() << "libkopete (avdevice): Device: " << name;
+ kDebug() << "libkopete (avdevice): Capabilities:";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_CAPTURE)
+ kDebug() << "libkopete (avdevice): Video capture";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_OUTPUT)
+ kDebug() << "libkopete (avdevice): Video output";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_OVERLAY)
+ kDebug() << "libkopete (avdevice): Video overlay";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_VBI_CAPTURE)
+ kDebug() << "libkopete (avdevice): VBI capture";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_VBI_OUTPUT)
+ kDebug() << "libkopete (avdevice): VBI output";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_RDS_CAPTURE)
+ kDebug() << "libkopete (avdevice): RDS capture";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_TUNER)
+ kDebug() << "libkopete (avdevice): Tuner IO";
+ if(V4L2_capabilities.capabilities & V4L2_CAP_AUDIO)
+ kDebug() << "libkopete (avdevice): Audio IO";
+;*/
+ kDebug() << "Device model: " << m_model;
+ kDebug() << "Device name : " << m_name;
+ kDebug() << "Capabilities:";
+ if(canCapture())
+ {
+ kDebug() << " Video capture";
+ }
+ if(canRead())
+ {
+ kDebug() << " Read";
+ }
+ if(canAsyncIO())
+ {
+ kDebug() << " Asynchronous input/output";
+ }
+ if(canStream())
+ {
+ kDebug() << " Streaming";
+ }
+ if(canChromakey())
+ {
+ kDebug() << " Video chromakey";
+ }
+ if(canScale())
+ {
+ kDebug() << " Video scales";
+ }
+ if(canOverlay())
+ {
+ kDebug() << " Video overlay";
+ }
+// kDebug() << "libkopete (avdevice): Audios : " << V4L_capabilities.audios;
+ kDebug() << " Max res: " << maxWidth() << " x " << maxHeight();
+ kDebug() << " Min res: " << minWidth() << " x " << minHeight();
+ kDebug() << " Inputs : " << inputs();
+ for (int loop=0; loop < inputs(); loop++)
+ kDebug() << "Input " << loop << ": " << m_input[loop].name << " (tuner: " << m_input[loop].hastuner << ")";
+ kDebug() << "showDeviceCapabilities() exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevicePool::initDevice()
+ */
+int VideoDevice::initDevice()
+{
+ /// @todo implement me
+ kDebug() << "initDevice() started";
+ if(-1 == descriptor)
+ {
+ kDebug() << "initDevice() Device is not open";
+ return EXIT_FAILURE;
+ }
+ m_io_method = IO_METHOD_NONE;
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ if(V4L2_capabilities.capabilities & V4L2_CAP_READWRITE)
+ {
+ m_videoread=true;
+ m_io_method = IO_METHOD_READ;
+ kDebug() << " Read/Write interface";
+ }
+ if(V4L2_capabilities.capabilities & V4L2_CAP_ASYNCIO)
+ {
+ m_videoasyncio=true;
+ kDebug() << " Async IO interface";
+ }
+ if(V4L2_capabilities.capabilities & V4L2_CAP_STREAMING)
+ {
+ m_videostream=true;
+ m_io_method = IO_METHOD_MMAP;
+// m_io_method = IO_METHOD_USERPTR;
+ kDebug() << " Streaming interface";
+ }
+ if(m_io_method==IO_METHOD_NONE)
+ {
+ kDebug() << "initDevice() Found no suitable input/output method for " << full_filename;
+ return EXIT_FAILURE;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ m_videoread=true;
+ m_io_method=IO_METHOD_READ;
+ if(-1 != xioctl(VIDIOCGFBUF,&V4L_videobuffer))
+ {
+// m_videostream=true;
+// m_io_method = IO_METHOD_MMAP;
+ kDebug() << " Streaming interface";
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+
+ break;
+ }
+
+// Select video input, video standard and tune here.
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == xioctl (VIDIOC_CROPCAP, &cropcap))
+ { // Errors ignored.
+ }
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c = cropcap.defrect; // reset to default
+ if (-1 == xioctl (VIDIOC_S_CROP, &crop))
+ {
+ switch (errno)
+ {
+ case EINVAL: break; // Cropping not supported.
+ default: break; // Errors ignored.
+ }
+ }
+#endif
+#endif
+
+ showDeviceCapabilities();
+ kDebug() << "initDevice() exited successfuly";
+ return EXIT_SUCCESS;
+}
+
+int VideoDevice::inputs()
+{
+ return m_input.size();
+}
+
+
+int VideoDevice::width()
+{
+ return currentwidth;
+}
+
+int VideoDevice::minWidth()
+{
+ return minwidth;
+}
+
+int VideoDevice::maxWidth()
+{
+ return maxwidth;
+}
+
+int VideoDevice::height()
+{
+ return currentheight;
+}
+
+int VideoDevice::minHeight()
+{
+ return minheight;
+}
+
+int VideoDevice::maxHeight()
+{
+ return maxheight;
+}
+
+int VideoDevice::setSize( int newwidth, int newheight)
+{
+kDebug() << "setSize(" << newwidth << ", " << newheight << ") called.";
+ if(isOpen())
+ {
+// It should not be there. It must remain in a completely distict place, cause this method should not change the pixelformat.
+// It shouldn't try to find a suitable pixel format this way. It should use values discovered by - detectPixelFormats() - to choose a valid one.
+ kDebug() << "Trying YUY422P";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_YUV422P))
+ {
+ kDebug() << "Device doesn't seem to support YUV422P format. Trying YUYV.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_YUYV))
+ {
+ kDebug() << "Device doesn't seem to support YUYV format. Trying UYVY.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_UYVY))
+ {
+ kDebug() << "Device doesn't seem to support UYVY format. Trying YUV420P.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_YUV420P))
+ {
+ kDebug() << "Device doesn't seem to support YUV420P format. Trying RGB24.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_RGB24))
+ {
+ kDebug() << "Device doesn't seem to support RGB24 format. Trying BGR24.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_BGR24))
+ {
+ kDebug() << "Device doesn't seem to support RGB24 format. Trying RGB32.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_RGB32))
+ {
+ kDebug() << "Device doesn't seem to support RGB32 format. Trying BGR32.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_BGR32))
+ {
+ kDebug() << "Device doesn't seem to support BGR32 format. Trying SBGGR8.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_SBGGR8))
+ {
+ kDebug() << "Device doesn't seem to support SBGGR8 format. Trying SN9C10X.";
+ if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_SN9C10X))
+ {
+ kDebug() << "Device doesn't seem to support BGR32 format. Fallback to it is not yet implemented.";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(newwidth > maxwidth ) newwidth = maxwidth;
+ if(newheight > maxheight) newheight = maxheight;
+ if(newwidth < minwidth ) newwidth = minwidth;
+ if(newheight < minheight) newheight = minheight;
+
+ currentwidth = newwidth;
+ currentheight = newheight;
+
+//kDebug() << "width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << width() << "x" << height();
+// Change resolution for the video device
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+// CLEAR (fmt);
+ if (-1 == xioctl (VIDIOC_G_FMT, &fmt))
+ {
+ kDebug() << "VIDIOC_G_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = width();
+ fmt.fmt.pix.height = height();
+ fmt.fmt.pix.field = V4L2_FIELD_ANY;
+ if (-1 == xioctl (VIDIOC_S_FMT, &fmt))
+ {
+ kDebug() << "VIDIOC_S_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ // Note VIDIOC_S_FMT may change width and height.
+ }
+ else
+ {
+// Buggy driver paranoia.
+kDebug() << "VIDIOC_S_FMT worked (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ unsigned int min = fmt.fmt.pix.width * 2;
+ if (fmt.fmt.pix.bytesperline < min)
+ {
+ fmt.fmt.pix.bytesperline = min;
+ }
+ min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
+ if (fmt.fmt.pix.sizeimage < min)
+ {
+ fmt.fmt.pix.sizeimage = min;
+ }
+ m_buffer_size=fmt.fmt.pix.sizeimage ;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_window V4L_videowindow;
+
+ if (xioctl (VIDIOCGWIN, &V4L_videowindow)== -1)
+ {
+ perror ("ioctl VIDIOCGWIN");
+// return (NULL);
+ }
+ V4L_videowindow.width = width();
+ V4L_videowindow.height = height();
+ V4L_videowindow.clipcount=0;
+ if (xioctl (VIDIOCSWIN, &V4L_videowindow)== -1)
+ {
+ perror ("ioctl VIDIOCSWIN");
+// return (NULL);
+ }
+kDebug() << "------------- width: " << V4L_videowindow.width << " Height: " << V4L_videowindow.height << " Clipcount: " << V4L_videowindow.clipcount << " -----------------";
+
+// kDebug() << "libkopete (avdevice): V4L_picture.palette: " << V4L_picture.palette << " Depth: " << V4L_picture.depth;
+
+/* if(-1 == xioctl(VIDIOCGFBUF,&V4L_videobuffer))
+ kDebug() << "libkopete (avdevice): VIDIOCGFBUF failed (" << errno << "): Device cannot stream";*/
+
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ m_buffer_size = width() * height() * pixelFormatDepth(m_pixelformat) / 8;
+kDebug() << "------------------------- ------- -- m_buffer_size: " << m_buffer_size << " !!! -- ------- -----------------------------------------";
+
+ m_currentbuffer.pixelformat=m_pixelformat;
+ m_currentbuffer.data.resize(m_buffer_size);
+
+ switch (m_io_method)
+ {
+ case IO_METHOD_NONE: break;
+ case IO_METHOD_READ: initRead (); break;
+ case IO_METHOD_MMAP: initMmap (); break;
+ case IO_METHOD_USERPTR: initUserptr (); break;
+ }
+
+kDebug() << "setSize(" << newwidth << ", " << newheight << ") exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+kDebug() << "setSize(" << newwidth << ", " << newheight << ") Device is not open.";
+ return EXIT_FAILURE;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+pixel_format VideoDevice::setPixelFormat(pixel_format newformat)
+{
+ pixel_format ret = PIXELFORMAT_NONE;
+//kDebug() << "called.";
+// Change the pixel format for the video device
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+// CLEAR (fmt);
+ if (-1 == xioctl (VIDIOC_G_FMT, &fmt))
+ {
+// return errnoReturn ("VIDIOC_S_FMT");
+// kDebug() << "VIDIOC_G_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ }
+ else
+ m_pixelformat = pixelFormatForPalette(fmt.fmt.pix.pixelformat);
+
+ fmt.fmt.pix.pixelformat = pixelFormatCode(newformat);
+ if (-1 == xioctl (VIDIOC_S_FMT, &fmt))
+ {
+// kDebug() << "VIDIOC_S_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
+ }
+ else
+ {
+ if (fmt.fmt.pix.pixelformat == (unsigned int) pixelFormatCode(newformat)) // Thih "if" (not what is contained within) is a fix for a bug in sn9c102 driver.
+ {
+ m_pixelformat = newformat;
+ ret = m_pixelformat;
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_picture V4L_picture;
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+// kDebug() << "V4L_picture.palette: " << V4L_picture.palette << " Depth: " << V4L_picture.depth;
+ V4L_picture.palette = pixelFormatCode(newformat);
+ V4L_picture.depth = pixelFormatDepth(newformat);
+ if(-1 == xioctl(VIDIOCSPICT,&V4L_picture))
+ {
+// kDebug() << "Device seems to not support " << pixelFormatName(newformat) << " format. Fallback to it is not yet implemented.";
+ }
+
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+
+// kDebug() << "V4L_picture.palette: " << V4L_picture.palette << " Depth: " << V4L_picture.depth;
+ m_pixelformat=pixelFormatForPalette(V4L_picture.palette);
+ if (m_pixelformat == newformat)
+ ret = newformat;
+
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return ret;
+}
+
+
+
+
+
+
+/*!
+ \fn Kopete::AV::VideoDevice::currentInput()
+ */
+int VideoDevice::currentInput()
+{
+ /// @todo implement me
+ if(isOpen())
+ {
+ return m_current_input;
+ }
+ return 0;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevice::selectInput(int input)
+ */
+int VideoDevice::selectInput(int newinput)
+{
+ /// @todo implement me
+ if(m_current_input >= inputs())
+ return EXIT_FAILURE;
+
+ if(isOpen())
+ {
+ switch (m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ if (-1 == ioctl (descriptor, VIDIOC_S_INPUT, &newinput))
+ {
+ perror ("VIDIOC_S_INPUT");
+ return EXIT_FAILURE;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ struct video_channel V4L_input;
+ V4L_input.channel=newinput;
+ V4L_input.norm=4; // Hey, it's plain wrong! It should be input's signal standard!
+ if (-1 == ioctl (descriptor, VIDIOCSCHAN, &V4L_input))
+ {
+ perror ("ioctl (VIDIOCSCHAN)");
+ return EXIT_FAILURE;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ kDebug() << "Selected input " << newinput << " (" << m_input[newinput].name << ")";
+ m_current_input = newinput;
+ setInputParameters();
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevice::setInputParameters()
+ */
+int VideoDevice::setInputParameters()
+{
+ /// @todo implement me
+ if( (isOpen()) && (m_current_input < inputs() ) )
+ {
+ setBrightness( getBrightness() );
+ setContrast( getContrast() );
+ setSaturation( getSaturation() );
+ setWhiteness( getWhiteness() );
+ setHue( getHue() );
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevice::startCapturing()
+ */
+int VideoDevice::startCapturing()
+{
+
+ kDebug() << "called.";
+ if(isOpen())
+ {
+ switch (m_io_method)
+ {
+ case IO_METHOD_NONE: // Device cannot capture frames
+ return EXIT_FAILURE;
+ break;
+ case IO_METHOD_READ: // Nothing to do
+ break;
+ case IO_METHOD_MMAP:
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ {
+ unsigned int loop;
+ for (loop = 0; loop < m_streambuffers; ++loop)
+ {
+ struct v4l2_buffer buf;
+ CLEAR (buf);
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = loop;
+ if (-1 == xioctl (VIDIOC_QBUF, &buf))
+ return errnoReturn ("VIDIOC_QBUF");
+ }
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == xioctl (VIDIOC_STREAMON, &type))
+ return errnoReturn ("VIDIOC_STREAMON");
+ }
+#endif
+#endif
+ break;
+ case IO_METHOD_USERPTR:
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ {
+ unsigned int loop;
+ for (loop = 0; loop < m_streambuffers; ++loop)
+ {
+ struct v4l2_buffer buf;
+ CLEAR (buf);
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.m.userptr = (unsigned long) m_rawbuffers[loop].start;
+ buf.length = m_rawbuffers[loop].length;
+ if (-1 == xioctl (VIDIOC_QBUF, &buf))
+ return errnoReturn ("VIDIOC_QBUF");
+ }
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == xioctl (VIDIOC_STREAMON, &type))
+ return errnoReturn ("VIDIOC_STREAMON");
+ }
+#endif
+#endif
+ break;
+ }
+
+ kDebug() << "exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevice::getFrame()
+ */
+int VideoDevice::getFrame()
+{
+ /// @todo implement me
+ ssize_t bytesread;
+
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ struct v4l2_buffer v4l2buffer;
+#endif
+#endif
+// kDebug() << "getFrame() called.";
+ if(isOpen())
+ {
+ switch (m_io_method)
+ {
+ case IO_METHOD_NONE: // Device cannot capture frames
+ return EXIT_FAILURE;
+ break;
+ case IO_METHOD_READ:
+// kDebug() << "Using IO_METHOD_READ.File descriptor: " << descriptor << " Buffer address: " << &m_currentbuffer.data[0] << " Size: " << m_currentbuffer.data.size();
+ if (m_currentbuffer.data.isEmpty())
+ return EXIT_FAILURE;
+
+#ifdef HAVE_LIBV4L2
+ bytesread = v4l2_read (descriptor, &m_currentbuffer.data[0], m_currentbuffer.data.size());
+#else
+ bytesread = read (descriptor, &m_currentbuffer.data[0], m_currentbuffer.data.size());
+#endif
+ if (-1 == bytesread) // must verify this point with ov511 driver.
+ {
+ kDebug() << "IO_METHOD_READ failed.";
+ switch (errno)
+ {
+ case EAGAIN:
+ return EXIT_FAILURE;
+ case EIO: /* Could ignore EIO, see spec. fall through */
+ default:
+ return errnoReturn ("read");
+ }
+ }
+ if((int)m_currentbuffer.data.size() < bytesread)
+ {
+ kDebug() << "IO_METHOD_READ returned less bytes (" << bytesread << ") than it was asked for (" << m_currentbuffer.data.size() <<").";
+ }
+ break;
+ case IO_METHOD_MMAP:
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ CLEAR (v4l2buffer);
+ v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2buffer.memory = V4L2_MEMORY_MMAP;
+ if (-1 == xioctl (VIDIOC_DQBUF, &v4l2buffer))
+ {
+ kDebug() << full_filename << " MMAPed getFrame failed.";
+ switch (errno)
+ {
+ case EAGAIN:
+ {
+ kDebug() << full_filename << " MMAPed getFrame failed: EAGAIN. Pointer: ";
+ return EXIT_FAILURE;
+ }
+ case EIO: /* Could ignore EIO, see spec. fall through */
+ default:
+ return errnoReturn ("VIDIOC_DQBUF");
+ }
+ }
+/* if (v4l2buffer.index < m_streambuffers)
+ return EXIT_FAILURE;*/ //it was an assert()
+// kDebug() << "m_rawbuffers[" << v4l2buffer.index << "].start: " << (void *)m_rawbuffers[v4l2buffer.index].start << " Size: " << m_currentbuffer.data.size();
+ if (m_currentbuffer.data.isEmpty() ||
+// v4l2buffer.index < 0 || // is always false: v4l2buffer.index is unsigned
+ (uint) m_rawbuffers.size() <= v4l2buffer.index)
+ return EXIT_FAILURE;
+
+ memcpy(&m_currentbuffer.data[0], m_rawbuffers[v4l2buffer.index].start, m_currentbuffer.data.size());
+ if (-1 == xioctl (VIDIOC_QBUF, &v4l2buffer))
+ return errnoReturn ("VIDIOC_QBUF");
+#endif
+#endif
+ break;
+ case IO_METHOD_USERPTR:
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ {
+ unsigned int i;
+ CLEAR (v4l2buffer);
+ v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2buffer.memory = V4L2_MEMORY_USERPTR;
+ if (-1 == xioctl (VIDIOC_DQBUF, &v4l2buffer))
+ {
+ switch (errno)
+ {
+ case EAGAIN:
+ return EXIT_FAILURE;
+ case EIO: /* Could ignore EIO, see spec. fall through */
+ default:
+ return errnoReturn ("VIDIOC_DQBUF");
+ }
+ }
+ if ((unsigned int) m_rawbuffers.size() < m_streambuffers)
+ return EXIT_FAILURE;
+
+ for (i = 0; i < m_streambuffers; ++i)
+ if (v4l2buffer.m.userptr == (unsigned long) m_rawbuffers[i].start && v4l2buffer.length == m_rawbuffers[i].length)
+ break;
+ if (i < m_streambuffers)
+ return EXIT_FAILURE;
+ if (-1 == xioctl (VIDIOC_QBUF, &v4l2buffer))
+ return errnoReturn ("VIDIOC_QBUF");
+ }
+#endif
+#endif
+ break;
+ }
+// kDebug() << "exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevice::getFrame(imagebuffer *imgbuffer)
+ */
+int VideoDevice::getFrame(imagebuffer *imgbuffer)
+{
+ if(imgbuffer)
+ {
+ getFrame();
+ imgbuffer->height = m_currentbuffer.height;
+ imgbuffer->width = m_currentbuffer.width;
+ imgbuffer->pixelformat = m_currentbuffer.pixelformat;
+ imgbuffer->data = m_currentbuffer.data;
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevice::getImage(const QImage *qimage)
+ */
+int VideoDevice::getImage(QImage *qimage)
+{
+ /// @todo implement me
+
+ // do NOT delete qimage here, as it is received as a parameter
+ if (qimage->width() != width() || qimage->height() != height())
+ *qimage = QImage(width(), height(), QImage::Format_RGB32);
+
+ if (!m_currentbuffer.data.size())
+ {
+ //there is no data so if we continue something will try access it (as in bug 161536) and crash kopete
+ //perhaps we should look at having the interface reflect when the camera isn't available? as it thinks
+ //it is for some reason, though the data size seems to be an ok check
+ return EXIT_FAILURE;
+ }
+
+ uchar *bits=qimage->bits();
+// kDebug() << "Capturing in " << pixelFormatName(m_currentbuffer.pixelformat);
+ switch(m_currentbuffer.pixelformat)
+ {
+ case PIXELFORMAT_NONE : break;
+
+// Packed RGB formats
+ case PIXELFORMAT_RGB332 :
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = (m_currentbuffer.data[step]>>5<<5)+(m_currentbuffer.data[step]>>5<<2)+(m_currentbuffer.data[step]>>6);
+ bits[loop+1] = (m_currentbuffer.data[step]>>2<<5)+(m_currentbuffer.data[step]<<3>>5<<2)+(m_currentbuffer.data[step]<<3>>6);
+ bits[loop+2] = (m_currentbuffer.data[step]<<6)+(m_currentbuffer.data[step]<<6>>2)+(m_currentbuffer.data[step]<<6>>4)+(m_currentbuffer.data[step]<<6>>6);
+ bits[loop+3] = 255;
+ step++;
+ }
+ }
+ break;
+ case PIXELFORMAT_RGB444 : break;
+ case PIXELFORMAT_RGB555 : break;
+ case PIXELFORMAT_RGB565 :
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = (m_currentbuffer.data[step]<<3)+(m_currentbuffer.data[step]<<3>>5);
+ bits[loop+1] = ((m_currentbuffer.data[step+1])<<5)|m_currentbuffer.data[step]>>5;
+ bits[loop+2] = ((m_currentbuffer.data[step+1])&248)+((m_currentbuffer.data[step+1])>>5);
+ bits[loop+3] = 255;
+ step+=2;
+ }
+ }
+ break;
+ case PIXELFORMAT_RGB555X: break;
+ case PIXELFORMAT_RGB565X: break;
+ case PIXELFORMAT_BGR24 :
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = m_currentbuffer.data[step+2];
+ bits[loop+1] = m_currentbuffer.data[step+1];
+ bits[loop+2] = m_currentbuffer.data[step];
+ bits[loop+3] = 255;
+ step+=3;
+ }
+ }
+ break;
+ case PIXELFORMAT_RGB24 :
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = m_currentbuffer.data[step];
+ bits[loop+1] = m_currentbuffer.data[step+1];
+ bits[loop+2] = m_currentbuffer.data[step+2];
+ bits[loop+3] = 255;
+ step+=3;
+ }
+ }
+ break;
+ case PIXELFORMAT_BGR32 :
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = m_currentbuffer.data[step+2];
+ bits[loop+1] = m_currentbuffer.data[step+1];
+ bits[loop+2] = m_currentbuffer.data[step];
+ bits[loop+3] = m_currentbuffer.data[step+3];
+ step+=4;
+ }
+ }
+ break;
+ case PIXELFORMAT_RGB32 : memcpy(bits,&m_currentbuffer.data[0], m_currentbuffer.data.size());
+ break;
+
+// Bayer RGB format
+ case PIXELFORMAT_SBGGR8 :
+ {
+ unsigned char *d = (unsigned char *) malloc (width() * height() * 3);
+ bayer2rgb24(d, &m_currentbuffer.data.first(), width(), height());
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = d[step+2];
+ bits[loop+1] = d[step+1];
+ bits[loop+2] = d[step];
+ bits[loop+3] = 255;
+ step+=3;
+ }
+ free(d);
+ }
+ break;
+
+// YUV formats
+ case PIXELFORMAT_GREY :
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = m_currentbuffer.data[step];
+ bits[loop+1] = m_currentbuffer.data[step];
+ bits[loop+2] = m_currentbuffer.data[step];
+ bits[loop+3] = 255;
+ step++;
+ }
+ }
+ break;
+ case PIXELFORMAT_YUYV:
+ case PIXELFORMAT_UYVY:
+ case PIXELFORMAT_YUV420P:
+ case PIXELFORMAT_YUV422P:
+ {
+ uchar *yptr, *cbptr, *crptr;
+ bool halfheight=false;
+ bool packed=false;
+// Adjust algorythm to specific YUV data arrangements.
+ if (m_currentbuffer.pixelformat == PIXELFORMAT_YUV420P)
+ halfheight=true;
+ if (m_currentbuffer.pixelformat == PIXELFORMAT_YUYV)
+ {
+ yptr = &m_currentbuffer.data[0];
+ cbptr = yptr + 1;
+ crptr = yptr + 3;
+ packed=true;
+ }
+ else if (m_currentbuffer.pixelformat == PIXELFORMAT_UYVY)
+ {
+ cbptr = &m_currentbuffer.data[0];
+ yptr = cbptr + 1;
+ crptr = cbptr + 2;
+ packed=true;
+ }
+ else
+ {
+ yptr = &m_currentbuffer.data[0];
+ cbptr = yptr + (width()*height());
+ crptr = cbptr + (width()*height()/(halfheight ? 4:2));
+ }
+
+ for(int y=0; y<height(); y++)
+ {
+// Decode scanline
+ for(int x=0; x<width(); x++)
+ {
+ int c,d,e;
+
+ if (packed)
+ {
+ c = (yptr[x<<1])-16;
+ d = (cbptr[x>>1<<2])-128;
+ e = (crptr[x>>1<<2])-128;
+ }
+ else
+ {
+ c = (yptr[x])-16;
+ d = (cbptr[x>>1])-128;
+ e = (crptr[x>>1])-128;
+ }
+
+ int r = (298 * c + 409 * e + 128)>>8;
+ int g = (298 * c - 100 * d - 208 * e + 128)>>8;
+ int b = (298 * c + 516 * d + 128)>>8;
+
+ if (r<0) r=0; if (r>255) r=255;
+ if (g<0) g=0; if (g>255) g=255;
+ if (b<0) b=0; if (b>255) b=255;
+
+ uint *p = (uint*)qimage->scanLine(y)+x;
+ *p = qRgba(r,g,b,255);
+
+ }
+// Jump to next line
+ if (packed)
+ {
+ yptr+=width()*2;
+ cbptr+=width()*2;
+ crptr+=width()*2;
+ }
+ else
+ {
+ yptr+=width();
+ if (!halfheight || y&1)
+ {
+ cbptr+=width()/2;
+ crptr+=width()/2;
+ }
+ }
+ }
+ }
+ break;
+
+// Compressed formats
+ case PIXELFORMAT_JPEG : break;
+ case PIXELFORMAT_MPEG : break;
+
+// Reserved formats
+ case PIXELFORMAT_DV : break;
+ case PIXELFORMAT_ET61X251:break;
+ case PIXELFORMAT_HI240 : break;
+ case PIXELFORMAT_HM12 : break;
+ case PIXELFORMAT_MJPEG : break;
+ case PIXELFORMAT_PWC1 : break;
+ case PIXELFORMAT_PWC2 : break;
+ case PIXELFORMAT_SN9C10X:
+ {
+ unsigned char *s = new unsigned char [width() * height()];
+ unsigned char *d = new unsigned char [width() * height() * 3];
+ sonix_decompress_init();
+ sonix_decompress(width(), height(), &m_currentbuffer.data.first(), s);
+ bayer2rgb24(d, s, width(), height());
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = d[step+2];
+ bits[loop+1] = d[step+1];
+ bits[loop+2] = d[step];
+ bits[loop+3] = 255;
+ step+=3;
+ }
+ delete[] s;
+ delete[] d;
+ }
+ case PIXELFORMAT_WNVA : break;
+ case PIXELFORMAT_YYUV : break;
+ }
+
+// Proccesses image for automatic Brightness/Contrast/Color correction
+ if (getAutoBrightnessContrast()||getAutoColorCorrection())
+ {
+ unsigned long long R=0, G=0, B=0, A=0, global=0;
+ int Rmax=0, Gmax=0, Bmax=0, Amax=0, globalmax=0;
+ int Rmin=255, Gmin=255, Bmin=255, Amin=255, globalmin=255;
+ int Rrange=255, Grange=255, Brange=255;
+
+// Finds minimum and maximum intensity for each color component
+ for(unsigned int loop=0;loop < (unsigned int) qimage->numBytes();loop+=4)
+ {
+ R+=bits[loop];
+ G+=bits[loop+1];
+ B+=bits[loop+2];
+// A+=bits[loop+3];
+ if (bits[loop] < Rmin) Rmin = bits[loop];
+ if (bits[loop+1] < Gmin) Gmin = bits[loop+1];
+ if (bits[loop+2] < Bmin) Bmin = bits[loop+2];
+// if (bits[loop+3] < Amin) Amin = bits[loop+3];
+ if (bits[loop] > Rmax) Rmax = bits[loop];
+ if (bits[loop+1] > Gmax) Gmax = bits[loop+1];
+ if (bits[loop+2] > Bmax) Bmax = bits[loop+2];
+// if (bits[loop+3] > Amax) Amax = bits[loop+3];
+ }
+ global = R + G + B;
+// Finds overall minimum and maximum intensity
+ if (Rmin > Gmin) globalmin = Gmin; else globalmin = Rmin; if (Bmin < globalmin) globalmin = Bmin;
+ if (Rmax > Gmax) globalmax = Rmax; else globalmax = Gmax; if (Bmax > globalmax) globalmax = Bmax;
+// If no color correction should be performed, simply level all the intensities so they're just the same.
+// In fact color correction should use the R, G and B variables to detect color deviation and "bump up" the saturation,
+// but it's computationally more expensive and the current way returns better results to the user.
+ if(!getAutoColorCorrection())
+ {
+ Rmin = globalmin ; Rmax = globalmax;
+ Gmin = globalmin ; Gmax = globalmax;
+ Bmin = globalmin ; Bmax = globalmax;
+// Amin = globalmin ; Amax = globalmax;
+ }
+// Calculates ranges and prevent a division by zero later on.
+ Rrange = Rmax - Rmin; if (Rrange == 0) Rrange = 255;
+ Grange = Gmax - Gmin; if (Grange == 0) Grange = 255;
+ Brange = Bmax - Bmin; if (Brange == 0) Brange = 255;
+// Arange = Amax - Amin; if (Arange == 0) Arange = 255;
+
+ kDebug() << " R: " << R << " G: " << G << " B: " << B << " A: " << A << " global: " << global <<
+ " Rmin: " << Rmin << " Gmin: " << Gmin << " Bmin: " << Bmin << " Amin: " << Amin << " globalmin: " << globalmin <<
+ " Rmax: " << Rmax << " Gmax: " << Gmax << " Bmax: " << Bmax << " Amax: " << Amax << " globalmax: " << globalmax ;
+
+ for(unsigned int loop=0;loop < (unsigned int) qimage->numBytes();loop+=4)
+ {
+ bits[loop] = (bits[loop] - Rmin) * 255 / (Rrange);
+ bits[loop+1] = (bits[loop+1] - Gmin) * 255 / (Grange);
+ bits[loop+2] = (bits[loop+2] - Bmin) * 255 / (Brange);
+// bits[loop+3] = (bits[loop+3] - Amin) * 255 / (Arange);
+ }
+ }
+ return EXIT_SUCCESS;
+}
+
+/*!
+ \fn VideoDevice::stopCapturing()
+ */
+int VideoDevice::stopCapturing()
+{
+ /// @todo implement me
+ kDebug() << "called.";
+ if(isOpen())
+ {
+ switch (m_io_method)
+ {
+ case IO_METHOD_NONE: // Device cannot capture frames
+ return EXIT_FAILURE;
+ break;
+ case IO_METHOD_READ: // Nothing to do
+ break;
+ case IO_METHOD_MMAP:
+ case IO_METHOD_USERPTR:
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ {
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == xioctl (VIDIOC_STREAMOFF, &type))
+ return errnoReturn ("VIDIOC_STREAMOFF");
+
+ if (m_io_method == IO_METHOD_MMAP)
+ {
+ unsigned int loop;
+ for (loop = 0; loop < m_streambuffers; ++loop)
+ {
+#ifdef HAVE_LIBV4L2
+ if (v4l2_munmap(m_rawbuffers[loop].start,m_rawbuffers[loop].length) != 0)
+#else
+ if (munmap(m_rawbuffers[loop].start,m_rawbuffers[loop].length) != 0)
+#endif
+ {
+ kDebug() << "unable to munmap.";
+ }
+ }
+ }
+ }
+#endif
+ break;
+ }
+ kDebug() << "exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+
+/*!
+ \fn VideoDevice::close()
+ */
+int VideoDevice::close()
+{
+ /// @todo implement me
+ kDebug() << " called.";
+ if(isOpen())
+ {
+ kDebug() << " Device is open. Trying to properly shutdown the device.";
+ stopCapturing();
+#ifdef HAVE_LIBV4L2
+ int ret = ::v4l2_close(descriptor);
+#else
+ int ret = ::close(descriptor);
+#endif
+ kDebug() << "::close() returns " << ret;
+ }
+ descriptor = -1;
+ return EXIT_SUCCESS;
+}
+
+float VideoDevice::getBrightness()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getBrightness();
+ else
+ return 0;
+}
+
+float VideoDevice::setBrightness(float brightness)
+{
+ kDebug() << "(" << brightness << ") called.";
+ m_input[m_current_input].setBrightness(brightness); // Just to check bounds
+
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ {
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ CLEAR (queryctrl);
+ queryctrl.id = V4L2_CID_BRIGHTNESS;
+
+ if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (errno != EINVAL)
+ {
+ kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ").";
+ } else
+ {
+ kDebug() << "Device doesn't support the Brightness control.";
+ }
+ } else
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ kDebug() << "Brightness control is disabled.";
+ } else
+ {
+ CLEAR (control);
+ control.id = V4L2_CID_BRIGHTNESS;
+ control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getBrightness());
+ control.value += queryctrl.minimum;
+
+ if (-1 == xioctl (VIDIOC_S_CTRL, &control))
+ {
+ kDebug() << "VIDIOC_S_CTRL failed (" << errno << ").";
+ }
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_picture V4L_picture;
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+ V4L_picture.brightness = uint(65535 * getBrightness());
+ if(-1 == xioctl(VIDIOCSPICT,&V4L_picture))
+ {
+ kDebug() << "Device seems to not support adjusting image brightness. Fallback to it is not yet implemented.";
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return getBrightness();
+}
+
+float VideoDevice::getContrast()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getContrast();
+ else
+ return 0;
+}
+
+float VideoDevice::setContrast(float contrast)
+{
+ kDebug() << "(" << contrast << ") called.";
+ m_input[m_current_input].setContrast(contrast); // Just to check bounds
+
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ {
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ CLEAR (queryctrl);
+ queryctrl.id = V4L2_CID_CONTRAST;
+
+ if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (errno != EINVAL)
+ {
+ kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ").";
+ } else
+ {
+ kDebug() << "Device doesn't support the Contrast control.";
+ }
+ } else
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ kDebug() << "Contrast control is disabled.";
+ } else
+ {
+ CLEAR (control);
+ control.id = V4L2_CID_CONTRAST;
+ control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getContrast());
+ control.value += queryctrl.minimum;
+
+ if (-1 == xioctl (VIDIOC_S_CTRL, &control))
+ {
+ kDebug() << "VIDIOC_S_CTRL failed (" << errno << ").";
+ }
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_picture V4L_picture;
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+ V4L_picture.contrast = uint(65535*getContrast());
+ if(-1 == xioctl(VIDIOCSPICT,&V4L_picture))
+ {
+ kDebug() << "Device seems to not support adjusting image contrast. Fallback to it is not yet implemented.";
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return getContrast();
+}
+
+float VideoDevice::getSaturation()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getSaturation();
+ else
+ return 0;
+}
+
+float VideoDevice::setSaturation(float saturation)
+{
+ kDebug() << "(" << saturation << ") called.";
+ m_input[m_current_input].setSaturation(saturation); // Just to check bounds
+
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ {
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ CLEAR (queryctrl);
+ queryctrl.id = V4L2_CID_SATURATION;
+
+ if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (errno != EINVAL)
+ {
+ kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ").";
+ } else
+ {
+ kDebug() << "Device doesn't support the Saturation control.";
+ }
+ } else
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ kDebug() << "Saturation control is disabled.";
+ } else
+ {
+ CLEAR (control);
+ control.id = V4L2_CID_SATURATION;
+ control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getSaturation());
+ control.value += queryctrl.minimum;
+
+ if (-1 == xioctl (VIDIOC_S_CTRL, &control))
+ {
+ kDebug() << "VIDIOC_S_CTRL failed (" << errno << ").";
+ }
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_picture V4L_picture;
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+ V4L_picture.colour = uint(65535*getSaturation());
+ if(-1 == xioctl(VIDIOCSPICT,&V4L_picture))
+ {
+ kDebug() << "Device seems to not support adjusting image saturation. Fallback to it is not yet implemented.";
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return getSaturation();
+}
+
+float VideoDevice::getWhiteness()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getWhiteness();
+ else
+ return 0;
+}
+
+float VideoDevice::setWhiteness(float whiteness)
+{
+ kDebug() << "(" << whiteness << ") called.";
+ m_input[m_current_input].setWhiteness(whiteness); // Just to check bounds
+
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ {
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ CLEAR (queryctrl);
+ queryctrl.id = V4L2_CID_WHITENESS;
+
+ if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (errno != EINVAL)
+ {
+ kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ").";
+ } else
+ {
+ kDebug() << "Device doesn't support the Whiteness control.";
+ }
+ } else
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ kDebug() << "Whiteness control is disabled.";
+ } else
+ {
+ CLEAR (control);
+ control.id = V4L2_CID_WHITENESS;
+ control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getWhiteness());
+ control.value += queryctrl.minimum;
+
+ if (-1 == xioctl (VIDIOC_S_CTRL, &control))
+ {
+ kDebug() << "VIDIOC_S_CTRL failed (" << errno << ").";
+ }
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_picture V4L_picture;
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+ V4L_picture.whiteness = uint(65535*getWhiteness());
+ if(-1 == xioctl(VIDIOCSPICT,&V4L_picture))
+ {
+ kDebug() << "Device seems to not support adjusting white level. Fallback to it is not yet implemented.";
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return getWhiteness();
+}
+
+float VideoDevice::getHue()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getHue();
+ else
+ return 0;
+}
+
+float VideoDevice::setHue(float hue)
+{
+ kDebug() << "(" << hue << ") called.";
+ m_input[m_current_input].setHue(hue); // Just to check bounds
+
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ {
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ CLEAR (queryctrl);
+ queryctrl.id = V4L2_CID_HUE;
+
+ if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (errno != EINVAL)
+ {
+ kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ").";
+ } else
+ {
+ kDebug() << "Device doesn't support the Hue control.";
+ }
+ } else
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ kDebug() << "Hue control is disabled.";
+ } else
+ {
+ CLEAR (control);
+ control.id = V4L2_CID_HUE;
+ control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getHue());
+ control.value += queryctrl.minimum;
+
+ if (-1 == xioctl (VIDIOC_S_CTRL, &control))
+ {
+ kDebug() << "VIDIOC_S_CTRL failed (" << errno << ").";
+ }
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ {
+ struct video_picture V4L_picture;
+ if(-1 == xioctl(VIDIOCGPICT, &V4L_picture))
+ {
+ kDebug() << "VIDIOCGPICT failed (" << errno << ").";
+ }
+ V4L_picture.hue = uint(65535*getHue());
+ if(-1 == xioctl(VIDIOCSPICT,&V4L_picture))
+ {
+ kDebug() << "Device seems to not support adjusting image hue. Fallback to it is not yet implemented.";
+ }
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return getHue();
+}
+
+
+bool VideoDevice::getAutoBrightnessContrast()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getAutoBrightnessContrast();
+ else
+ return false;
+}
+
+bool VideoDevice::setAutoBrightnessContrast(bool brightnesscontrast)
+{
+ kDebug() << "VideoDevice::setAutoBrightnessContrast(" << brightnesscontrast << ") called.";
+ if (m_current_input < m_input.size() )
+ {
+ m_input[m_current_input].setAutoBrightnessContrast(brightnesscontrast);
+ return m_input[m_current_input].getAutoBrightnessContrast();
+ }
+ else
+ return false;
+
+}
+
+bool VideoDevice::getAutoColorCorrection()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getAutoColorCorrection();
+ else
+ return false;
+}
+
+bool VideoDevice::setAutoColorCorrection(bool colorcorrection)
+{
+ kDebug() << "VideoDevice::setAutoColorCorrection(" << colorcorrection << ") called.";
+ if (m_current_input < m_input.size() )
+ {
+ m_input[m_current_input].setAutoColorCorrection(colorcorrection);
+ return m_input[m_current_input].getAutoColorCorrection();
+ }
+ else
+ return false;
+}
+
+bool VideoDevice::getImageAsMirror()
+{
+ if (m_current_input < m_input.size() )
+ return m_input[m_current_input].getImageAsMirror();
+ else
+ return false;
+}
+
+bool VideoDevice::setImageAsMirror(bool imageasmirror)
+{
+ kDebug() << "VideoDevice::setImageAsMirror(" << imageasmirror << ") called.";
+ if (m_current_input < m_input.size() )
+ {
+ m_input[m_current_input].setImageAsMirror(imageasmirror);
+ return m_input[m_current_input].getImageAsMirror();
+ }
+ else
+ return false;
+}
+
+pixel_format VideoDevice::pixelFormatForPalette( int palette )
+{
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ switch(palette)
+ {
+ case 0 : return PIXELFORMAT_NONE; break;
+
+// Packed RGB formats
+ case V4L2_PIX_FMT_RGB332 : return PIXELFORMAT_RGB332; break;
+#if defined( V4L2_PIX_FMT_RGB444 )
+ case V4L2_PIX_FMT_RGB444 : return PIXELFORMAT_RGB444; break;
+#endif
+ case V4L2_PIX_FMT_RGB555 : return PIXELFORMAT_RGB555; break;
+ case V4L2_PIX_FMT_RGB565 : return PIXELFORMAT_RGB565; break;
+ case V4L2_PIX_FMT_RGB555X : return PIXELFORMAT_RGB555X; break;
+ case V4L2_PIX_FMT_RGB565X : return PIXELFORMAT_RGB565X; break;
+ case V4L2_PIX_FMT_BGR24 : return PIXELFORMAT_BGR24; break;
+ case V4L2_PIX_FMT_RGB24 : return PIXELFORMAT_RGB24; break;
+ case V4L2_PIX_FMT_BGR32 : return PIXELFORMAT_BGR32; break;
+ case V4L2_PIX_FMT_RGB32 : return PIXELFORMAT_RGB32; break;
+
+// Bayer RGB format
+ case V4L2_PIX_FMT_SBGGR8 : return PIXELFORMAT_SBGGR8; break;
+
+// YUV formats
+ case V4L2_PIX_FMT_GREY : return PIXELFORMAT_GREY; break;
+ case V4L2_PIX_FMT_YUYV : return PIXELFORMAT_YUYV; break;
+ case V4L2_PIX_FMT_UYVY : return PIXELFORMAT_UYVY; break;
+ case V4L2_PIX_FMT_YUV420 : return PIXELFORMAT_YUV420P; break;
+ case V4L2_PIX_FMT_YUV422P : return PIXELFORMAT_YUV422P; break;
+
+// Compressed formats
+ case V4L2_PIX_FMT_JPEG : return PIXELFORMAT_JPEG; break;
+ case V4L2_PIX_FMT_MPEG : return PIXELFORMAT_MPEG; break;
+
+// Reserved formats
+ case V4L2_PIX_FMT_DV : return PIXELFORMAT_DV; break;
+ case V4L2_PIX_FMT_ET61X251 : return PIXELFORMAT_ET61X251; break;
+ case V4L2_PIX_FMT_HI240 : return PIXELFORMAT_HI240; break;
+#if defined( V4L2_PIX_FMT_HM12 )
+ case V4L2_PIX_FMT_HM12 : return PIXELFORMAT_HM12; break;
+#endif
+ case V4L2_PIX_FMT_MJPEG : return PIXELFORMAT_MJPEG; break;
+ case V4L2_PIX_FMT_PWC1 : return PIXELFORMAT_PWC1; break;
+ case V4L2_PIX_FMT_PWC2 : return PIXELFORMAT_PWC2; break;
+ case V4L2_PIX_FMT_SN9C10X : return PIXELFORMAT_SN9C10X; break;
+ case V4L2_PIX_FMT_WNVA : return PIXELFORMAT_WNVA; break;
+ case V4L2_PIX_FMT_YYUV : return PIXELFORMAT_YYUV; break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ switch(palette)
+ {
+ case 0 : return PIXELFORMAT_NONE; break;
+ case VIDEO_PALETTE_GREY : return PIXELFORMAT_GREY; break;
+ case VIDEO_PALETTE_HI240 : return PIXELFORMAT_RGB332; break;
+ case VIDEO_PALETTE_RGB555 : return PIXELFORMAT_RGB555; break;
+ case VIDEO_PALETTE_RGB565 : return PIXELFORMAT_RGB565; break;
+ case VIDEO_PALETTE_RGB24 : return PIXELFORMAT_RGB24; break;
+ case VIDEO_PALETTE_RGB32 : return PIXELFORMAT_RGB32; break;
+ case VIDEO_PALETTE_YUYV : return PIXELFORMAT_YUYV; break;
+ case VIDEO_PALETTE_UYVY : return PIXELFORMAT_UYVY; break;
+ case VIDEO_PALETTE_YUV420 :
+ case VIDEO_PALETTE_YUV420P : return PIXELFORMAT_YUV420P; break;
+ case VIDEO_PALETTE_YUV422P : return PIXELFORMAT_YUV422P; break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ return PIXELFORMAT_NONE; break;
+ }
+ return PIXELFORMAT_NONE;
+}
+
+int VideoDevice::pixelFormatCode(pixel_format pixelformat)
+{
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ switch(pixelformat)
+ {
+ case PIXELFORMAT_NONE : return 0; break;
+
+// Packed RGB formats
+ case PIXELFORMAT_RGB332 : return V4L2_PIX_FMT_RGB332; break;
+#if defined( V4L2_PIX_FMT_RGB444 )
+ case PIXELFORMAT_RGB444 : return V4L2_PIX_FMT_RGB444; break;
+#endif
+ case PIXELFORMAT_RGB555 : return V4L2_PIX_FMT_RGB555; break;
+ case PIXELFORMAT_RGB565 : return V4L2_PIX_FMT_RGB565; break;
+ case PIXELFORMAT_RGB555X: return V4L2_PIX_FMT_RGB555X; break;
+ case PIXELFORMAT_RGB565X: return V4L2_PIX_FMT_RGB565X; break;
+ case PIXELFORMAT_BGR24 : return V4L2_PIX_FMT_BGR24; break;
+ case PIXELFORMAT_RGB24 : return V4L2_PIX_FMT_RGB24; break;
+ case PIXELFORMAT_BGR32 : return V4L2_PIX_FMT_BGR32; break;
+ case PIXELFORMAT_RGB32 : return V4L2_PIX_FMT_RGB32; break;
+
+// Bayer RGB format
+ case PIXELFORMAT_SBGGR8 : return V4L2_PIX_FMT_SBGGR8; break;
+
+// YUV formats
+ case PIXELFORMAT_GREY : return V4L2_PIX_FMT_GREY; break;
+ case PIXELFORMAT_YUYV : return V4L2_PIX_FMT_YUYV; break;
+ case PIXELFORMAT_UYVY : return V4L2_PIX_FMT_UYVY; break;
+ case PIXELFORMAT_YUV420P: return V4L2_PIX_FMT_YUV420; break;
+ case PIXELFORMAT_YUV422P: return V4L2_PIX_FMT_YUV422P; break;
+
+// Compressed formats
+ case PIXELFORMAT_JPEG : return V4L2_PIX_FMT_JPEG; break;
+ case PIXELFORMAT_MPEG : return V4L2_PIX_FMT_MPEG; break;
+
+// Reserved formats
+ case PIXELFORMAT_DV : return V4L2_PIX_FMT_DV; break;
+ case PIXELFORMAT_ET61X251:return V4L2_PIX_FMT_ET61X251;break;
+ case PIXELFORMAT_HI240 : return V4L2_PIX_FMT_HI240; break;
+#if defined( V4L2_PIX_FMT_HM12 )
+ case PIXELFORMAT_HM12 : return V4L2_PIX_FMT_HM12; break;
+#endif
+ case PIXELFORMAT_MJPEG : return V4L2_PIX_FMT_MJPEG; break;
+ case PIXELFORMAT_PWC1 : return V4L2_PIX_FMT_PWC1; break;
+ case PIXELFORMAT_PWC2 : return V4L2_PIX_FMT_PWC2; break;
+ case PIXELFORMAT_SN9C10X: return V4L2_PIX_FMT_SN9C10X; break;
+ case PIXELFORMAT_WNVA : return V4L2_PIX_FMT_WNVA; break;
+ case PIXELFORMAT_YYUV : return V4L2_PIX_FMT_YYUV; break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ switch(pixelformat)
+ {
+ case PIXELFORMAT_NONE : return 0; break;
+
+// Packed RGB formats
+ case PIXELFORMAT_RGB332 : return VIDEO_PALETTE_HI240; break;
+ case PIXELFORMAT_RGB444 : return 0; break;
+ case PIXELFORMAT_RGB555 : return VIDEO_PALETTE_RGB555; break;
+ case PIXELFORMAT_RGB565 : return VIDEO_PALETTE_RGB565; break;
+ case PIXELFORMAT_RGB555X: return 0; break;
+ case PIXELFORMAT_RGB565X: return 0; break;
+ case PIXELFORMAT_BGR24 : return 0; break;
+ case PIXELFORMAT_RGB24 : return VIDEO_PALETTE_RGB24; break;
+ case PIXELFORMAT_BGR32 : return 0; break;
+ case PIXELFORMAT_RGB32 : return VIDEO_PALETTE_RGB32; break;
+
+// Bayer RGB format
+ case PIXELFORMAT_SBGGR8 : return 0; break;
+
+// YUV formats
+ case PIXELFORMAT_GREY : return VIDEO_PALETTE_GREY; break;
+ case PIXELFORMAT_YUYV : return VIDEO_PALETTE_YUYV; break;
+ case PIXELFORMAT_UYVY : return VIDEO_PALETTE_UYVY; break;
+ case PIXELFORMAT_YUV420P: return VIDEO_PALETTE_YUV420; break;
+ case PIXELFORMAT_YUV422P: return VIDEO_PALETTE_YUV422P; break;
+
+// Compressed formats
+ case PIXELFORMAT_JPEG : return 0; break;
+ case PIXELFORMAT_MPEG : return 0; break;
+
+// Reserved formats
+ case PIXELFORMAT_DV : return 0; break;
+ case PIXELFORMAT_ET61X251:return 0; break;
+ case PIXELFORMAT_HI240 : return VIDEO_PALETTE_HI240; break;
+ case PIXELFORMAT_HM12 : return 0; break;
+ case PIXELFORMAT_MJPEG : return 0; break;
+ case PIXELFORMAT_PWC1 : return 0; break;
+ case PIXELFORMAT_PWC2 : return 0; break;
+ case PIXELFORMAT_SN9C10X: return 0; break;
+ case PIXELFORMAT_WNVA : return 0; break;
+ case PIXELFORMAT_YYUV : return 0; break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ return PIXELFORMAT_NONE; break;
+ }
+ return PIXELFORMAT_NONE;
+}
+
+int VideoDevice::pixelFormatDepth(pixel_format pixelformat)
+{
+ switch(pixelformat)
+ {
+ case PIXELFORMAT_NONE : return 0; break;
+
+// Packed RGB formats
+ case PIXELFORMAT_RGB332 : return 8; break;
+ case PIXELFORMAT_RGB444 : return 16; break;
+ case PIXELFORMAT_RGB555 : return 16; break;
+ case PIXELFORMAT_RGB565 : return 16; break;
+ case PIXELFORMAT_RGB555X: return 16; break;
+ case PIXELFORMAT_RGB565X: return 16; break;
+ case PIXELFORMAT_BGR24 : return 24; break;
+ case PIXELFORMAT_RGB24 : return 24; break;
+ case PIXELFORMAT_BGR32 : return 32; break;
+ case PIXELFORMAT_RGB32 : return 32; break;
+
+// Bayer RGB format
+ case PIXELFORMAT_SBGGR8 : return 0; break;
+
+// YUV formats
+ case PIXELFORMAT_GREY : return 8; break;
+ case PIXELFORMAT_YUYV : return 16; break;
+ case PIXELFORMAT_UYVY : return 16; break;
+ case PIXELFORMAT_YUV420P: return 16; break;
+ case PIXELFORMAT_YUV422P: return 16; break;
+
+// Compressed formats
+ case PIXELFORMAT_JPEG : return 0; break;
+ case PIXELFORMAT_MPEG : return 0; break;
+
+// Reserved formats
+ case PIXELFORMAT_DV : return 0; break;
+ case PIXELFORMAT_ET61X251:return 0; break;
+ case PIXELFORMAT_HI240 : return 8; break;
+ case PIXELFORMAT_HM12 : return 0; break;
+ case PIXELFORMAT_MJPEG : return 0; break;
+ case PIXELFORMAT_PWC1 : return 0; break;
+ case PIXELFORMAT_PWC2 : return 0; break;
+ case PIXELFORMAT_SN9C10X: return 0; break;
+ case PIXELFORMAT_WNVA : return 0; break;
+ case PIXELFORMAT_YYUV : return 0; break;
+ }
+ return 0;
+}
+
+QString VideoDevice::pixelFormatName(pixel_format pixelformat)
+{
+ QString returnvalue;
+ returnvalue = "None";
+ switch(pixelformat)
+ {
+ case PIXELFORMAT_NONE : returnvalue = "None"; break;
+
+// Packed RGB formats
+ case PIXELFORMAT_RGB332 : returnvalue = "8-bit RGB332"; break;
+ case PIXELFORMAT_RGB444 : returnvalue = "8-bit RGB444"; break;
+ case PIXELFORMAT_RGB555 : returnvalue = "16-bit RGB555"; break;
+ case PIXELFORMAT_RGB565 : returnvalue = "16-bit RGB565"; break;
+ case PIXELFORMAT_RGB555X: returnvalue = "16-bit RGB555X"; break;
+ case PIXELFORMAT_RGB565X: returnvalue = "16-bit RGB565X"; break;
+ case PIXELFORMAT_BGR24 : returnvalue = "24-bit BGR24"; break;
+ case PIXELFORMAT_RGB24 : returnvalue = "24-bit RGB24"; break;
+ case PIXELFORMAT_BGR32 : returnvalue = "32-bit BGR32"; break;
+ case PIXELFORMAT_RGB32 : returnvalue = "32-bit RGB32"; break;
+
+// Bayer RGB format
+ case PIXELFORMAT_SBGGR8 : returnvalue = "Bayer RGB format"; break;
+
+// YUV formats
+ case PIXELFORMAT_GREY : returnvalue = "8-bit Grayscale"; break;
+ case PIXELFORMAT_YUYV : returnvalue = "Packed YUV 4:2:2"; break;
+ case PIXELFORMAT_UYVY : returnvalue = "Packed YVU 4:2:2"; break;
+ case PIXELFORMAT_YUV420P: returnvalue = "Planar YUV 4:2:0"; break;
+ case PIXELFORMAT_YUV422P: returnvalue = "Planar YUV 4:2:2"; break;
+
+
+// Compressed formats
+ case PIXELFORMAT_JPEG : returnvalue = "JPEG image"; break;
+ case PIXELFORMAT_MPEG : returnvalue = "MPEG stream"; break;
+
+// Reserved formats
+ case PIXELFORMAT_DV : returnvalue = "DV (unknown)"; break;
+ case PIXELFORMAT_ET61X251:returnvalue = "ET61X251"; break;
+ case PIXELFORMAT_HI240 : returnvalue = "8-bit HI240 (RGB332)"; break;
+ case PIXELFORMAT_HM12 : returnvalue = "Packed YUV 4:2:2"; break;
+ case PIXELFORMAT_MJPEG : returnvalue = "8-bit Grayscale"; break;
+ case PIXELFORMAT_PWC1 : returnvalue = "PWC1"; break;
+ case PIXELFORMAT_PWC2 : returnvalue = "PWC2"; break;
+ case PIXELFORMAT_SN9C10X: returnvalue = "SN9C102"; break;
+ case PIXELFORMAT_WNVA : returnvalue = "Winnov Videum"; break;
+ case PIXELFORMAT_YYUV : returnvalue = "YYUV (unknown)"; break;
+ }
+ return returnvalue;
+}
+
+QString VideoDevice::pixelFormatName(int pixelformat)
+{
+ QString returnvalue;
+ returnvalue = "None";
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ switch(pixelformat)
+ {
+ case 0 : returnvalue = pixelFormatName(PIXELFORMAT_NONE); break;
+
+// Packed RGB formats
+ case V4L2_PIX_FMT_RGB332 : returnvalue = pixelFormatName(PIXELFORMAT_RGB332); break;
+#if defined( V4L2_PIX_FMT_RGB444 )
+ case V4L2_PIX_FMT_RGB444 : returnvalue = pixelFormatName(PIXELFORMAT_RGB444); break;
+#endif
+ case V4L2_PIX_FMT_RGB555 : returnvalue = pixelFormatName(PIXELFORMAT_RGB555); break;
+ case V4L2_PIX_FMT_RGB565 : returnvalue = pixelFormatName(PIXELFORMAT_RGB565); break;
+ case V4L2_PIX_FMT_RGB555X : returnvalue = pixelFormatName(PIXELFORMAT_RGB555X); break;
+ case V4L2_PIX_FMT_RGB565X : returnvalue = pixelFormatName(PIXELFORMAT_RGB565X); break;
+ case V4L2_PIX_FMT_BGR24 : returnvalue = pixelFormatName(PIXELFORMAT_BGR24); break;
+ case V4L2_PIX_FMT_RGB24 : returnvalue = pixelFormatName(PIXELFORMAT_RGB24); break;
+ case V4L2_PIX_FMT_BGR32 : returnvalue = pixelFormatName(PIXELFORMAT_BGR32); break;
+ case V4L2_PIX_FMT_RGB32 : returnvalue = pixelFormatName(PIXELFORMAT_RGB32); break;
+
+// Bayer RGB format
+ case V4L2_PIX_FMT_SBGGR8 : returnvalue = pixelFormatName(PIXELFORMAT_SBGGR8); break;
+
+// YUV formats
+ case V4L2_PIX_FMT_GREY : returnvalue = pixelFormatName(PIXELFORMAT_GREY); break;
+ case V4L2_PIX_FMT_YUYV : returnvalue = pixelFormatName(PIXELFORMAT_YUYV); break;
+ case V4L2_PIX_FMT_UYVY : returnvalue = pixelFormatName(PIXELFORMAT_UYVY); break;
+ case V4L2_PIX_FMT_YUV420 : returnvalue = pixelFormatName(PIXELFORMAT_YUV420P); break;
+ case V4L2_PIX_FMT_YUV422P : returnvalue = pixelFormatName(PIXELFORMAT_YUV422P); break;
+
+// Compressed formats
+ case V4L2_PIX_FMT_JPEG : returnvalue = pixelFormatName(PIXELFORMAT_JPEG); break;
+ case V4L2_PIX_FMT_MPEG : returnvalue = pixelFormatName(PIXELFORMAT_MPEG); break;
+
+// Reserved formats
+ case V4L2_PIX_FMT_DV : returnvalue = pixelFormatName(PIXELFORMAT_DV); break;
+ case V4L2_PIX_FMT_ET61X251 : returnvalue = pixelFormatName(PIXELFORMAT_ET61X251); break;
+ case V4L2_PIX_FMT_HI240 : returnvalue = pixelFormatName(PIXELFORMAT_HI240); break;
+#if defined( V4L2_PIX_FMT_HM12 )
+ case V4L2_PIX_FMT_HM12 : returnvalue = pixelFormatName(PIXELFORMAT_HM12); break;
+#endif
+ case V4L2_PIX_FMT_MJPEG : returnvalue = pixelFormatName(PIXELFORMAT_MJPEG); break;
+ case V4L2_PIX_FMT_PWC1 : returnvalue = pixelFormatName(PIXELFORMAT_PWC1); break;
+ case V4L2_PIX_FMT_PWC2 : returnvalue = pixelFormatName(PIXELFORMAT_PWC2); break;
+ case V4L2_PIX_FMT_SN9C10X : returnvalue = pixelFormatName(PIXELFORMAT_SN9C10X); break;
+ case V4L2_PIX_FMT_WNVA : returnvalue = pixelFormatName(PIXELFORMAT_WNVA); break;
+ case V4L2_PIX_FMT_YYUV : returnvalue = pixelFormatName(PIXELFORMAT_YYUV); break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ switch(pixelformat)
+ {
+ case VIDEO_PALETTE_GREY : returnvalue = pixelFormatName(PIXELFORMAT_GREY); break;
+ case VIDEO_PALETTE_HI240 : returnvalue = pixelFormatName(PIXELFORMAT_RGB332); break;
+ case VIDEO_PALETTE_RGB555 : returnvalue = pixelFormatName(PIXELFORMAT_RGB555); break;
+ case VIDEO_PALETTE_RGB565 : returnvalue = pixelFormatName(PIXELFORMAT_RGB565); break;
+ case VIDEO_PALETTE_RGB24 : returnvalue = pixelFormatName(PIXELFORMAT_RGB24); break;
+ case VIDEO_PALETTE_RGB32 : returnvalue = pixelFormatName(PIXELFORMAT_RGB32); break;
+ case VIDEO_PALETTE_YUYV : returnvalue = pixelFormatName(PIXELFORMAT_YUYV); break;
+ case VIDEO_PALETTE_UYVY : returnvalue = pixelFormatName(PIXELFORMAT_UYVY); break;
+ case VIDEO_PALETTE_YUV420 :
+ case VIDEO_PALETTE_YUV420P : returnvalue = pixelFormatName(PIXELFORMAT_YUV420P); break;
+ case VIDEO_PALETTE_YUV422P : returnvalue = pixelFormatName(PIXELFORMAT_YUV422P); break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return returnvalue;
+}
+
+int VideoDevice::detectPixelFormats()
+{
+ int err = 0;
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ fmtdesc.index = 0;
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ while ( err == 0 )
+ {
+ if (-1 == xioctl (VIDIOC_ENUM_FMT, &fmtdesc))
+// if (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0 )
+ {
+ perror("VIDIOC_ENUM_FMT");
+ err = errno;
+ }
+ else
+ {
+ kDebug () << fmtdesc.pixelformat << " " << pixelFormatName(fmtdesc.pixelformat); // Need a cleanup. PixelFormatForPalette is a really bad name
+ fmtdesc.index++;
+ }
+ }
+// break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+// TODO: THis thing can be used to detec what pixel formats are supported in a API-independent way, but V4L2 has VIDIOC_ENUM_PIXFMT.
+// The correct thing to do is to isolate these calls and do a proper implementation for V4L and another for V4L2 when this thing will be migrated to a plugin architecture.
+
+// Packed RGB formats
+ kDebug() << "Supported pixel formats:";
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB332)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB332); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB444)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB444); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB555)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB555); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB565)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB565); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB555X)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB555X); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB565X)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB565X); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_BGR24)) { kDebug() << pixelFormatName(PIXELFORMAT_BGR24); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB24)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB24); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_BGR32)) { kDebug() << pixelFormatName(PIXELFORMAT_BGR32); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB32)) { kDebug() << pixelFormatName(PIXELFORMAT_RGB32); }
+
+// Bayer RGB format
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_SBGGR8)) { kDebug() << pixelFormatName(PIXELFORMAT_SBGGR8); }
+
+// YUV formats
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_GREY)) { kDebug() << pixelFormatName(PIXELFORMAT_GREY); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YUYV)) { kDebug() << pixelFormatName(PIXELFORMAT_YUYV); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_UYVY)) { kDebug() << pixelFormatName(PIXELFORMAT_UYVY); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YUV420P)) { kDebug() << pixelFormatName(PIXELFORMAT_YUV420P); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YUV422P)) { kDebug() << pixelFormatName(PIXELFORMAT_YUV422P); }
+
+// Compressed formats
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_JPEG)) { kDebug() << pixelFormatName(PIXELFORMAT_JPEG); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_MPEG)) { kDebug() << pixelFormatName(PIXELFORMAT_MPEG); }
+
+// Reserved formats
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_DV)) { kDebug() << pixelFormatName(PIXELFORMAT_DV); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_ET61X251)) { kDebug() << pixelFormatName(PIXELFORMAT_ET61X251); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_HI240)) { kDebug() << pixelFormatName(PIXELFORMAT_HI240); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_HM12)) { kDebug() << pixelFormatName(PIXELFORMAT_HM12); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_MJPEG)) { kDebug() << pixelFormatName(PIXELFORMAT_MJPEG); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_PWC1)) { kDebug() << pixelFormatName(PIXELFORMAT_PWC1); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_PWC2)) { kDebug() << pixelFormatName(PIXELFORMAT_PWC2); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_SN9C10X)) { kDebug() << pixelFormatName(PIXELFORMAT_SN9C10X); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_WNVA)) { kDebug() << pixelFormatName(PIXELFORMAT_WNVA); }
+ if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YYUV)) { kDebug() << pixelFormatName(PIXELFORMAT_YYUV); }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ return PIXELFORMAT_NONE; break;
+ }
+ return PIXELFORMAT_NONE;
+}
+
+__u64 VideoDevice::signalStandardCode(signal_standard standard)
+{
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ switch(standard)
+ {
+ case STANDARD_PAL_B : return V4L2_STD_PAL_B; break;
+ case STANDARD_PAL_B1 : return V4L2_STD_PAL_B1; break;
+ case STANDARD_PAL_G : return V4L2_STD_PAL_G; break;
+ case STANDARD_PAL_H : return V4L2_STD_PAL_H; break;
+ case STANDARD_PAL_I : return V4L2_STD_PAL_I; break;
+ case STANDARD_PAL_D : return V4L2_STD_PAL_D; break;
+ case STANDARD_PAL_D1 : return V4L2_STD_PAL_D1; break;
+ case STANDARD_PAL_K : return V4L2_STD_PAL_K; break;
+
+ case STANDARD_PAL_M : return V4L2_STD_PAL_M; break;
+ case STANDARD_PAL_N : return V4L2_STD_PAL_N; break;
+ case STANDARD_PAL_Nc : return V4L2_STD_PAL_Nc; break;
+ case STANDARD_PAL_60 : return V4L2_STD_PAL_60; break;
+
+ case STANDARD_NTSC_M : return V4L2_STD_NTSC_M; break;
+ case STANDARD_NTSC_M_JP : return V4L2_STD_NTSC_M_JP; break;
+ case STANDARD_NTSC_443 : return V4L2_STD_NTSC_443; break;
+ case STANDARD_NTSC_M_KR : return V4L2_STD_NTSC_M_KR; break;
+
+ case STANDARD_SECAM_B : return V4L2_STD_SECAM_B; break;
+ case STANDARD_SECAM_D : return V4L2_STD_SECAM_D; break;
+ case STANDARD_SECAM_G : return V4L2_STD_SECAM_G; break;
+ case STANDARD_SECAM_H : return V4L2_STD_SECAM_H; break;
+ case STANDARD_SECAM_K : return V4L2_STD_SECAM_K; break;
+ case STANDARD_SECAM_K1 : return V4L2_STD_SECAM_K1; break;
+ case STANDARD_SECAM_L : return V4L2_STD_SECAM_L; break;
+ case STANDARD_SECAM_LC : return V4L2_STD_SECAM_LC; break;
+
+ case STANDARD_ATSC_8_VSB: return V4L2_STD_ATSC_8_VSB; break;
+ case STANDARD_ATSC_16_VSB:return V4L2_STD_ATSC_16_VSB; break;
+
+ case STANDARD_PAL_BG : return V4L2_STD_PAL_BG; break;
+ case STANDARD_PAL_DK : return V4L2_STD_PAL_DK; break;
+ case STANDARD_PAL : return V4L2_STD_PAL; break;
+ case STANDARD_NTSC : return V4L2_STD_NTSC; break;
+ case STANDARD_SECAM_DK : return V4L2_STD_SECAM_DK; break;
+ case STANDARD_SECAM : return V4L2_STD_SECAM; break;
+
+ case STANDARD_MN : return V4L2_STD_MN; break;
+ case STANDARD_B : return V4L2_STD_B; break;
+ case STANDARD_GH : return V4L2_STD_GH; break;
+ case STANDARD_DK : return V4L2_STD_DK; break;
+
+ case STANDARD_525_60 : return V4L2_STD_525_60; break;
+ case STANDARD_625_50 : return V4L2_STD_625_50; break;
+ case STANDARD_ATSC : return V4L2_STD_ATSC; break;
+
+ case STANDARD_UNKNOWN : return V4L2_STD_UNKNOWN; break;
+ case STANDARD_ALL : return V4L2_STD_ALL; break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ switch(standard)
+ {
+ case STANDARD_PAL_B : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_B1 : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_G : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_H : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_I : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_D : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_D1 : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_K : return VIDEO_MODE_PAL; break;
+
+ case STANDARD_PAL_M : return 5; break; // Undocumented value found to be compatible with V4L bttv driver
+ case STANDARD_PAL_N : return 6; break; // Undocumented value found to be compatible with V4L bttv driver
+ case STANDARD_PAL_Nc : return 4; break; // Undocumented value found to be compatible with V4L bttv driver
+ case STANDARD_PAL_60 : return VIDEO_MODE_PAL; break;
+
+ case STANDARD_NTSC_M : return VIDEO_MODE_NTSC; break;
+ case STANDARD_NTSC_M_JP : return 7; break; // Undocumented value found to be compatible with V4L bttv driver
+ case STANDARD_NTSC_443 : return VIDEO_MODE_NTSC; break;
+ case STANDARD_NTSC_M_KR : return VIDEO_MODE_NTSC; break;
+
+ case STANDARD_SECAM_B : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_D : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_G : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_H : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_K : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_K1 : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_L : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM_LC : return VIDEO_MODE_SECAM; break;
+
+ case STANDARD_ATSC_8_VSB: return VIDEO_MODE_AUTO; break;
+ case STANDARD_ATSC_16_VSB:return VIDEO_MODE_AUTO; break;
+
+ case STANDARD_PAL_BG : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL_DK : return VIDEO_MODE_PAL; break;
+ case STANDARD_PAL : return VIDEO_MODE_PAL; break;
+ case STANDARD_NTSC : return VIDEO_MODE_NTSC; break;
+ case STANDARD_SECAM_DK : return VIDEO_MODE_SECAM; break;
+ case STANDARD_SECAM : return VIDEO_MODE_SECAM; break;
+
+ case STANDARD_MN : return VIDEO_MODE_AUTO; break;
+ case STANDARD_B : return VIDEO_MODE_AUTO; break;
+ case STANDARD_GH : return VIDEO_MODE_AUTO; break;
+ case STANDARD_DK : return VIDEO_MODE_AUTO; break;
+
+ case STANDARD_525_60 : return VIDEO_MODE_PAL; break;
+ case STANDARD_625_50 : return VIDEO_MODE_SECAM; break;
+ case STANDARD_ATSC : return VIDEO_MODE_AUTO; break;
+
+ case STANDARD_UNKNOWN : return VIDEO_MODE_AUTO; break;
+ case STANDARD_ALL : return VIDEO_MODE_AUTO; break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ return STANDARD_UNKNOWN; break;
+ }
+ return STANDARD_UNKNOWN;
+}
+
+QString VideoDevice::signalStandardName(signal_standard standard)
+{
+ QString returnvalue;
+ returnvalue = "None";
+ switch(standard)
+ {
+ case STANDARD_PAL_B : returnvalue = "PAL-B"; break;
+ case STANDARD_PAL_B1 : returnvalue = "PAL-B1"; break;
+ case STANDARD_PAL_G : returnvalue = "PAL-G"; break;
+ case STANDARD_PAL_H : returnvalue = "PAL-H"; break;
+ case STANDARD_PAL_I : returnvalue = "PAL-I"; break;
+ case STANDARD_PAL_D : returnvalue = "PAL-D"; break;
+ case STANDARD_PAL_D1 : returnvalue = "PAL-D1"; break;
+ case STANDARD_PAL_K : returnvalue = "PAL-K"; break;
+
+ case STANDARD_PAL_M : returnvalue = "PAL-M"; break;
+ case STANDARD_PAL_N : returnvalue = "PAL-N"; break;
+ case STANDARD_PAL_Nc : returnvalue = "PAL-Nc"; break;
+ case STANDARD_PAL_60 : returnvalue = "PAL-60"; break;
+
+ case STANDARD_NTSC_M : returnvalue = "NTSC-M"; break;
+ case STANDARD_NTSC_M_JP : returnvalue = "NTSC-M(JP)"; break;
+ case STANDARD_NTSC_443 : returnvalue = "NTSC-443"; break;
+ case STANDARD_NTSC_M_KR : returnvalue = "NTSC-M(KR)"; break;
+
+ case STANDARD_SECAM_B : returnvalue = "SECAM-B"; break;
+ case STANDARD_SECAM_D : returnvalue = "SECAM-D"; break;
+ case STANDARD_SECAM_G : returnvalue = "SECAM-G"; break;
+ case STANDARD_SECAM_H : returnvalue = "SECAM-H"; break;
+ case STANDARD_SECAM_K : returnvalue = "SECAM-K"; break;
+ case STANDARD_SECAM_K1 : returnvalue = "SECAM-K1"; break;
+ case STANDARD_SECAM_L : returnvalue = "SECAM-L"; break;
+ case STANDARD_SECAM_LC : returnvalue = "SECAM-LC"; break;
+
+ case STANDARD_ATSC_8_VSB: returnvalue = "ATSC-8-VSB"; break;
+ case STANDARD_ATSC_16_VSB:returnvalue = "ATSC-16-VSB"; break;
+
+ case STANDARD_PAL_BG : returnvalue = "PAL-BG"; break;
+ case STANDARD_PAL_DK : returnvalue = "PAL-DK"; break;
+ case STANDARD_PAL : returnvalue = "PAL"; break;
+ case STANDARD_NTSC : returnvalue = "NTSC"; break;
+ case STANDARD_SECAM_DK : returnvalue = "SECAM-DK"; break;
+ case STANDARD_SECAM : returnvalue = "SECAM"; break;
+
+ case STANDARD_MN : returnvalue = "DK"; break;
+ case STANDARD_B : returnvalue = "B"; break;
+ case STANDARD_GH : returnvalue = "GH"; break;
+ case STANDARD_DK : returnvalue = "DK"; break;
+
+ case STANDARD_525_60 : returnvalue = "525 lines 60Hz";break;
+ case STANDARD_625_50 : returnvalue = "625 lines 50Hz";break;
+ case STANDARD_ATSC : returnvalue = "ATSC"; break;
+
+ case STANDARD_UNKNOWN : returnvalue = "Unknown"; break;
+ case STANDARD_ALL : returnvalue = "All"; break;
+ }
+ return returnvalue;
+}
+
+QString VideoDevice::signalStandardName(int standard)
+{
+ QString returnvalue;
+ returnvalue = "None";
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+ switch(standard)
+ {
+ case V4L2_STD_PAL_B : returnvalue = signalStandardName(STANDARD_PAL_B); break;
+ case V4L2_STD_PAL_B1 : returnvalue = signalStandardName(STANDARD_PAL_B1); break;
+ case V4L2_STD_PAL_G : returnvalue = signalStandardName(STANDARD_PAL_G); break;
+ case V4L2_STD_PAL_H : returnvalue = signalStandardName(STANDARD_PAL_H); break;
+ case V4L2_STD_PAL_I : returnvalue = signalStandardName(STANDARD_PAL_I); break;
+ case V4L2_STD_PAL_D : returnvalue = signalStandardName(STANDARD_PAL_D); break;
+ case V4L2_STD_PAL_D1 : returnvalue = signalStandardName(STANDARD_PAL_D1); break;
+ case V4L2_STD_PAL_K : returnvalue = signalStandardName(STANDARD_PAL_K); break;
+ case V4L2_STD_PAL_M : returnvalue = signalStandardName(STANDARD_PAL_M); break;
+ case V4L2_STD_PAL_N : returnvalue = signalStandardName(STANDARD_PAL_N); break;
+ case V4L2_STD_PAL_Nc : returnvalue = signalStandardName(STANDARD_PAL_Nc); break;
+ case V4L2_STD_PAL_60 : returnvalue = signalStandardName(STANDARD_PAL_60); break;
+ case V4L2_STD_NTSC_M : returnvalue = signalStandardName(STANDARD_NTSC_M); break;
+ case V4L2_STD_NTSC_M_JP : returnvalue = signalStandardName(STANDARD_NTSC_M_JP); break;
+ case V4L2_STD_NTSC_443 : returnvalue = signalStandardName(STANDARD_NTSC_443); break; // Commented out because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id
+ case V4L2_STD_NTSC_M_KR : returnvalue = signalStandardName(STANDARD_NTSC_M_KR); break; // Commented out because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id
+ case V4L2_STD_SECAM_B : returnvalue = signalStandardName(STANDARD_SECAM_B); break;
+ case V4L2_STD_SECAM_D : returnvalue = signalStandardName(STANDARD_SECAM_D); break;
+ case V4L2_STD_SECAM_G : returnvalue = signalStandardName(STANDARD_SECAM_G); break;
+ case V4L2_STD_SECAM_H : returnvalue = signalStandardName(STANDARD_SECAM_H); break;
+ case V4L2_STD_SECAM_K : returnvalue = signalStandardName(STANDARD_SECAM_K); break;
+ case V4L2_STD_SECAM_K1 : returnvalue = signalStandardName(STANDARD_SECAM_K1); break;
+ case V4L2_STD_SECAM_L : returnvalue = signalStandardName(STANDARD_SECAM_L); break;
+ case V4L2_STD_SECAM_LC : returnvalue = signalStandardName(STANDARD_SECAM_LC); break;
+
+ case V4L2_STD_ATSC_8_VSB: returnvalue = signalStandardName(STANDARD_ATSC_8_VSB);break;
+ case V4L2_STD_ATSC_16_VSB:returnvalue = signalStandardName(STANDARD_ATSC_16_VSB);break;
+
+ case V4L2_STD_PAL_BG : returnvalue = signalStandardName(STANDARD_PAL_BG); break;
+ case V4L2_STD_PAL_DK : returnvalue = signalStandardName(STANDARD_PAL_DK); break;
+ case V4L2_STD_PAL : returnvalue = signalStandardName(STANDARD_PAL); break;
+ case V4L2_STD_NTSC : returnvalue = signalStandardName(STANDARD_NTSC); break;
+ case V4L2_STD_SECAM_DK : returnvalue = signalStandardName(STANDARD_SECAM_DK); break;
+ case V4L2_STD_SECAM : returnvalue = signalStandardName(STANDARD_SECAM); break;
+
+ case V4L2_STD_MN : returnvalue = signalStandardName(STANDARD_MN); break;
+ case V4L2_STD_B : returnvalue = signalStandardName(STANDARD_B); break;
+ case V4L2_STD_GH : returnvalue = signalStandardName(STANDARD_GH); break;
+ case V4L2_STD_DK : returnvalue = signalStandardName(STANDARD_DK); break;
+
+ case V4L2_STD_525_60 : returnvalue = signalStandardName(STANDARD_525_60); break;
+ case V4L2_STD_625_50 : returnvalue = signalStandardName(STANDARD_625_50); break;
+ case V4L2_STD_ATSC : returnvalue = signalStandardName(STANDARD_ATSC); break;
+
+ case V4L2_STD_UNKNOWN : returnvalue = signalStandardName(STANDARD_UNKNOWN); break;
+ case V4L2_STD_ALL : returnvalue = signalStandardName(STANDARD_ALL); break;
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ switch(standard)
+ {
+ case VIDEO_MODE_PAL : returnvalue = signalStandardName(STANDARD_PAL); break;
+ case VIDEO_MODE_NTSC : returnvalue = signalStandardName(STANDARD_NTSC); break;
+ case VIDEO_MODE_SECAM : returnvalue = signalStandardName(STANDARD_SECAM); break;
+ case VIDEO_MODE_AUTO : returnvalue = signalStandardName(STANDARD_ALL); break; // It must be disabled until I find a correct way to handle those non-standard bttv modes
+// case VIDEO_MODE_PAL_Nc : returnvalue = signalStandardName(STANDARD_PAL_Nc); break; // Undocumented value found to be compatible with V4L bttv driver
+ case VIDEO_MODE_PAL_M : returnvalue = signalStandardName(STANDARD_PAL_M); break; // Undocumented value found to be compatible with V4L bttv driver
+ case VIDEO_MODE_PAL_N : returnvalue = signalStandardName(STANDARD_PAL_N); break; // Undocumented value found to be compatible with V4L bttv driver
+ case VIDEO_MODE_NTSC_JP : returnvalue = signalStandardName(STANDARD_NTSC_M_JP); break; // Undocumented value found to be compatible with V4L bttv driver
+ }
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ return returnvalue;
+}
+
+/*!
+ \fn VideoDevice::detectSignalStandards()
+// this must be done once for each _input_.
+ */
+int VideoDevice::detectSignalStandards()
+{
+ kDebug() << "called.";
+ if(isOpen())
+ {
+ switch(m_driver)
+ {
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ case VIDEODEV_DRIVER_V4L2:
+
+
+ struct v4l2_input input;
+ struct v4l2_standard standard;
+
+ memset (&input, 0, sizeof (input));
+
+ if (-1 == xioctl (VIDIOC_G_INPUT, &input.index)) {
+ perror ("VIDIOC_G_INPUT");
+ return EXIT_FAILURE;
+ }
+
+ if (-1 == xioctl (VIDIOC_ENUMINPUT, &input)) {
+ perror ("VIDIOC_ENUM_INPUT");
+ return EXIT_FAILURE;
+ }
+
+// printf ("Current input %s supports:\n", input.name);
+
+ memset (&standard, 0, sizeof (standard));
+ standard.index = 0;
+
+ while (0 == xioctl (VIDIOC_ENUMSTD, &standard)) {
+ if (standard.id & input.std)
+ {
+// kDebug() << standard.name;
+ kDebug() << signalStandardName(standard.id) << " (" << standard.id << ")" << V4L2_STD_NTSC;
+ }
+
+ standard.index++;
+ }
+
+/* EINVAL indicates the end of the enumeration, which cannot be
+ empty unless this device falls under the USB exception. */
+
+ if (errno != EINVAL || standard.index == 0) {
+ perror ("VIDIOC_ENUMSTD");
+ return EXIT_FAILURE;
+ }
+
+
+ break;
+#endif
+ case VIDEODEV_DRIVER_V4L:
+ break;
+#endif
+ case VIDEODEV_DRIVER_NONE:
+ default:
+ break;
+ }
+ //FIXME: return a real value
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevice::initRead()
+ */
+int VideoDevice::initRead()
+{
+ /// @todo implement me
+
+ kDebug() << "called.";
+ if(isOpen())
+ {
+ m_rawbuffers.resize(1);
+ if (m_rawbuffers.size()==0)
+ {
+ fprintf (stderr, "Out of memory\n");
+ return EXIT_FAILURE;
+ }
+ kDebug() << "m_buffer_size: " << m_buffer_size;
+
+// m_rawbuffers[0].pixelformat=m_pixelformat;
+ m_rawbuffers[0].length = m_buffer_size;
+ m_rawbuffers[0].start = (uchar *)malloc (m_buffer_size);
+
+ if (!m_rawbuffers[0].start)
+ {
+ fprintf (stderr, "Out of memory\n");
+ return EXIT_FAILURE;
+ }
+ kDebug() << "exited successfuly.";
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+
+/*!
+ \fn VideoDevice::initMmap()
+ */
+int VideoDevice::initMmap()
+{
+ /// @todo implement me
+#define BUFFERS 2
+ if(isOpen())
+ {
+ kDebug() << full_filename << " Trying to MMAP";
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ struct v4l2_requestbuffers req;
+
+ CLEAR (req);
+
+ req.count = BUFFERS;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+
+ if (-1 == xioctl (VIDIOC_REQBUFS, &req))
+ {
+ if (EINVAL == errno)
+ {
+ kDebug() << full_filename << " does not support memory mapping";
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ return errnoReturn ("VIDIOC_REQBUFS");
+ }
+ }
+
+ if (req.count < BUFFERS)
+ {
+ kDebug() << "Insufficient buffer memory on " << full_filename;
+ return EXIT_FAILURE;
+ }
+
+ m_rawbuffers.resize(req.count);
+
+ if (m_rawbuffers.size()==0)
+ {
+ kDebug() << "Out of memory";
+ return EXIT_FAILURE;
+ }
+
+ for (m_streambuffers = 0; m_streambuffers < req.count; ++m_streambuffers)
+ {
+ struct v4l2_buffer v4l2buffer;
+
+ CLEAR (v4l2buffer);
+
+ v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2buffer.memory = V4L2_MEMORY_MMAP;
+ v4l2buffer.index = m_streambuffers;
+
+ if (-1 == xioctl (VIDIOC_QUERYBUF, &v4l2buffer))
+ return errnoReturn ("VIDIOC_QUERYBUF");
+
+ m_rawbuffers[m_streambuffers].length = v4l2buffer.length;
+#ifdef HAVE_LIBV4L2
+ m_rawbuffers[m_streambuffers].start = (uchar *) v4l2_mmap (NULL /* start anywhere */, v4l2buffer.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, descriptor, v4l2buffer.m.offset);
+#else
+ m_rawbuffers[m_streambuffers].start = (uchar *) mmap (NULL /* start anywhere */, v4l2buffer.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, descriptor, v4l2buffer.m.offset);
+#endif
+
+ if (MAP_FAILED == m_rawbuffers[m_streambuffers].start)
+ return errnoReturn ("mmap");
+ }
+#endif
+ m_currentbuffer.data.resize(m_rawbuffers[0].length); // Makes the imagesize.data buffer size equal to the rawbuffer size
+ kDebug() << full_filename << " m_currentbuffer.data.size(): " << m_currentbuffer.data.size();
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+
+/*!
+ \fn VideoDevice::initUserptr()
+ */
+int VideoDevice::initUserptr()
+{
+ /// @todo implement me
+ if(isOpen())
+ {
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ struct v4l2_requestbuffers req;
+
+ CLEAR (req);
+
+ req.count = 2;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ if (-1 == xioctl (VIDIOC_REQBUFS, &req))
+ {
+ if (EINVAL == errno)
+ {
+ kDebug() << full_filename << " does not support memory mapping";
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ return errnoReturn ("VIDIOC_REQBUFS");
+ }
+ }
+
+ m_rawbuffers.resize(4);
+
+ if (m_rawbuffers.size()==0)
+ {
+ fprintf (stderr, "Out of memory\n");
+ return EXIT_FAILURE;
+ }
+
+ for (m_streambuffers = 0; m_streambuffers < 4; ++m_streambuffers)
+ {
+ m_rawbuffers[m_streambuffers].length = m_buffer_size;
+ m_rawbuffers[m_streambuffers].start = (uchar *) malloc (m_buffer_size);
+
+ if (!m_rawbuffers[m_streambuffers].start)
+ {
+ kDebug() << "Out of memory";
+ return EXIT_FAILURE;
+ }
+ }
+#endif
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+}
+
+bool VideoDevice::canCapture()
+{
+ return m_videocapture;
+}
+
+bool VideoDevice::canChromakey()
+{
+ return m_videochromakey;
+}
+
+bool VideoDevice::canScale()
+{
+ return m_videoscale;
+}
+
+bool VideoDevice::canOverlay()
+{
+ return m_videooverlay;
+}
+
+bool VideoDevice::canRead()
+{
+ return m_videoread;
+}
+
+bool VideoDevice::canAsyncIO()
+{
+ return m_videoasyncio;
+}
+
+bool VideoDevice::canStream()
+{
+ return m_videostream;
+}
+
+void VideoDevice::setUdi( const QString & udi )
+{
+ m_udi = udi;
+}
+
+QString VideoDevice::udi() const
+{
+ return m_udi;
+}
+
+}
+
+}
diff --git a/src/kvilib/ext/avdevice/videodevice.h b/src/kvilib/ext/avdevice/videodevice.h
new file mode 100644
index 000000000..20dcbc90f
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevice.h
@@ -0,0 +1,374 @@
+//=============================================================================
+//
+// File : videodevice.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevice.h - Kopete Video Device Low-level Support
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#define ENABLE_AV
+
+#ifndef KOPETE_AVVIDEODEVICELISTITEM_H
+#define KOPETE_AVVIDEODEVICELISTITEM_H
+
+//#include <config-kopete.h>
+
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+
+#if defined(__linux__) && defined(ENABLE_AV)
+
+#include <asm/types.h>
+#undef __STRICT_ANSI__
+#ifndef __u64 //required by videodev.h
+#define __u64 unsigned long long
+#endif // __u64
+#ifndef __s64 //required by videodev.h
+#define __s64 signed long long
+#endif // __s64
+
+
+#ifndef pgoff_t
+#define pgoff_t unsigned long
+#endif
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/videodev.h>
+#define VIDEO_MODE_PAL_Nc 3
+#define VIDEO_MODE_PAL_M 4
+#define VIDEO_MODE_PAL_N 5
+#define VIDEO_MODE_NTSC_JP 6
+#define __STRICT_ANSI__
+
+#ifdef HAVE_LIBV4L2
+#include <libv4l2.h>
+#endif // HAVE_V4L2
+
+#endif // __linux__
+
+#include <qstring.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <q3valuevector.h>
+#include <kcombobox.h>
+
+#include "videoinput.h"
+
+namespace Kopete {
+
+namespace AV {
+
+/**
+@author Kopete Developers
+*/
+typedef enum
+{
+ VIDEODEV_DRIVER_NONE
+#if defined( __linux__) && defined(ENABLE_AV)
+ ,
+ VIDEODEV_DRIVER_V4L
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ ,
+ VIDEODEV_DRIVER_V4L2
+#endif
+#endif
+} videodev_driver;
+
+typedef enum
+{
+// Packed RGB formats
+ PIXELFORMAT_NONE = 0,
+ PIXELFORMAT_GREY = (1 << 0),
+ PIXELFORMAT_RGB332 = (1 << 1),
+ PIXELFORMAT_RGB444 = (1 << 2),
+ PIXELFORMAT_RGB555 = (1 << 3),
+ PIXELFORMAT_RGB565 = (1 << 4),
+ PIXELFORMAT_RGB555X = (1 << 5),
+ PIXELFORMAT_RGB565X = (1 << 6),
+ PIXELFORMAT_BGR24 = (1 << 7),
+ PIXELFORMAT_RGB24 = (1 << 8),
+ PIXELFORMAT_BGR32 = (1 << 9),
+ PIXELFORMAT_RGB32 = (1 << 10),
+
+// Bayer RGB format
+ PIXELFORMAT_SBGGR8 = (1 << 11),
+
+// YUV formats
+ PIXELFORMAT_YUYV = (1 << 12),
+ PIXELFORMAT_UYVY = (1 << 13),
+ PIXELFORMAT_YUV420P = (1 << 14),
+ PIXELFORMAT_YUV422P = (1 << 15),
+
+// Compressed formats
+ PIXELFORMAT_JPEG = (1 << 16),
+ PIXELFORMAT_MPEG = (1 << 17),
+
+// Reserved formats
+ PIXELFORMAT_DV = (1 << 18),
+ PIXELFORMAT_ET61X251 = (1 << 19),
+ PIXELFORMAT_HI240 = (1 << 20),
+ PIXELFORMAT_HM12 = (1 << 21),
+ PIXELFORMAT_MJPEG = (1 << 22),
+ PIXELFORMAT_PWC1 = (1 << 23),
+ PIXELFORMAT_PWC2 = (1 << 24),
+ PIXELFORMAT_SN9C10X = (1 << 25),
+ PIXELFORMAT_WNVA = (1 << 26),
+ PIXELFORMAT_YYUV = (1 << 27)
+
+// PIXELFORMAT_ALL = 0x00003FFF
+} pixel_format;
+
+typedef enum
+{
+// One bit for each
+ STANDARD_PAL_B = (1 << 0),
+ STANDARD_PAL_B1 = (1 << 1),
+ STANDARD_PAL_G = (1 << 2),
+ STANDARD_PAL_H = (1 << 3),
+ STANDARD_PAL_I = (1 << 4),
+ STANDARD_PAL_D = (1 << 5),
+ STANDARD_PAL_D1 = (1 << 6),
+ STANDARD_PAL_K = (1 << 7),
+
+ STANDARD_PAL_M = (1 << 8),
+ STANDARD_PAL_N = (1 << 9),
+ STANDARD_PAL_Nc = (1 << 10),
+ STANDARD_PAL_60 = (1 << 11),
+// STANDARD_PAL_60 is a hybrid standard with 525 lines, 60 Hz refresh rate, and PAL color modulation with a 4.43 MHz color subcarrier. Some PAL video recorders can play back NTSC tapes in this mode for display on a 50/60 Hz agnostic PAL TV.
+
+ STANDARD_NTSC_M = (1 << 12),
+ STANDARD_NTSC_M_JP = (1 << 13),
+ STANDARD_NTSC_443 = (1 << 14),
+// STANDARD_NTSC_443 is a hybrid standard with 525 lines, 60 Hz refresh rate, and NTSC color modulation with a 4.43 MHz color subcarrier.
+ STANDARD_NTSC_M_KR = (1 << 15),
+
+ STANDARD_SECAM_B = (1 << 16),
+ STANDARD_SECAM_D = (1 << 17),
+ STANDARD_SECAM_G = (1 << 18),
+ STANDARD_SECAM_H = (1 << 19),
+ STANDARD_SECAM_K = (1 << 20),
+ STANDARD_SECAM_K1 = (1 << 21),
+ STANDARD_SECAM_L = (1 << 22),
+ STANDARD_SECAM_LC = (1 << 23),
+
+// ATSC/HDTV
+ STANDARD_ATSC_8_VSB = (1 << 24),
+ STANDARD_ATSC_16_VSB = (1 << 25),
+
+// Some common needed stuff
+ STANDARD_PAL_BG = ( STANDARD_PAL_B | STANDARD_PAL_B1 | STANDARD_PAL_G ),
+ STANDARD_PAL_DK = ( STANDARD_PAL_D | STANDARD_PAL_D1 | STANDARD_PAL_K ),
+ STANDARD_PAL = ( STANDARD_PAL_BG | STANDARD_PAL_DK | STANDARD_PAL_H | STANDARD_PAL_I ),
+ STANDARD_NTSC = ( STANDARD_NTSC_M | STANDARD_NTSC_M_JP| STANDARD_NTSC_M_KR ),
+ STANDARD_SECAM_DK = ( STANDARD_SECAM_D | STANDARD_SECAM_K | STANDARD_SECAM_K1 ),
+ STANDARD_SECAM = ( STANDARD_SECAM_B | STANDARD_SECAM_G | STANDARD_SECAM_H | STANDARD_SECAM_DK | STANDARD_SECAM_L | STANDARD_SECAM_LC ),
+
+// some merged standards */
+ STANDARD_MN = ( STANDARD_PAL_M | STANDARD_PAL_N | STANDARD_PAL_Nc | STANDARD_NTSC ),
+ STANDARD_B = ( STANDARD_PAL_B | STANDARD_PAL_B1 | STANDARD_SECAM_B ),
+ STANDARD_GH = ( STANDARD_PAL_G | STANDARD_PAL_H | STANDARD_SECAM_G | STANDARD_SECAM_H ),
+ STANDARD_DK = ( STANDARD_PAL_DK | STANDARD_SECAM_DK ),
+
+ STANDARD_525_60 = ( STANDARD_PAL_M | STANDARD_PAL_60 | STANDARD_NTSC | STANDARD_NTSC_443),
+ STANDARD_625_50 = ( STANDARD_PAL | STANDARD_PAL_N | STANDARD_PAL_Nc | STANDARD_SECAM),
+ STANDARD_ATSC = ( STANDARD_ATSC_8_VSB | STANDARD_ATSC_16_VSB ),
+
+ STANDARD_UNKNOWN = 0,
+ STANDARD_ALL = ( STANDARD_525_60 | STANDARD_625_50)
+} signal_standard;
+
+
+typedef enum
+{
+ IO_METHOD_NONE,
+ IO_METHOD_READ,
+ IO_METHOD_MMAP,
+ IO_METHOD_USERPTR
+} io_method;
+
+struct imagebuffer
+{
+ int height;
+ int width;
+ pixel_format pixelformat;
+ QVector <uchar> data; // maybe it should be a rawbuffer instead of it? It could make us avoid a memory copy
+};
+struct rawbuffer // raw buffer
+{
+ uchar * start;
+ size_t length;
+};
+
+
+class VideoDevice{
+public:
+ VideoDevice();
+ virtual ~VideoDevice();
+ int setFileName(QString filename);
+ virtual int open();
+ virtual bool isOpen();
+ virtual int checkDevice();
+ int showDeviceCapabilities();
+ virtual int initDevice();
+ int inputs();
+ int width();
+ int minWidth();
+ int maxWidth();
+ int height();
+ int minHeight();
+ int maxHeight();
+ virtual int setSize( int newwidth, int newheight);
+
+ virtual pixel_format setPixelFormat(pixel_format newformat);
+ int pixelFormatCode(pixel_format pixelformat);
+ pixel_format pixelFormatForPalette( int palette );
+ int pixelFormatDepth(pixel_format pixelformat);
+ QString pixelFormatName(pixel_format pixelformat);
+ QString pixelFormatName(int pixelformat);
+ int detectPixelFormats();
+
+ __u64 signalStandardCode(signal_standard standard);
+ QString signalStandardName(signal_standard standard);
+ QString signalStandardName(int standard);
+ int detectSignalStandards();
+
+ int currentInput();
+ int selectInput(int input);
+ int setInputParameters();
+ virtual int startCapturing();
+ virtual int getFrame();
+ virtual int getFrame(imagebuffer *imgbuffer);
+ virtual int getImage(QImage *qimage);
+ virtual int stopCapturing();
+ virtual int close();
+
+ float getBrightness();
+ float setBrightness(float brightness);
+ float getContrast();
+ float setContrast(float contrast);
+ float getSaturation();
+ float setSaturation(float saturation);
+ float getWhiteness();
+ float setWhiteness(float whiteness);
+ float getHue();
+ float setHue(float Hue);
+
+ bool getAutoBrightnessContrast();
+ bool setAutoBrightnessContrast(bool brightnesscontrast);
+ bool getAutoColorCorrection();
+ bool setAutoColorCorrection(bool colorcorrection);
+ bool getImageAsMirror();
+ bool setImageAsMirror(bool imageasmirror);
+
+ bool canCapture();
+ bool canChromakey();
+ bool canScale();
+ bool canOverlay();
+ bool canRead();
+ bool canAsyncIO();
+ bool canStream();
+
+ void setUdi( const QString & );
+ QString udi() const;
+ QString m_model;
+ QString m_name;
+ size_t m_modelindex; // Defines what's the number of a device when more than 1 device of a given model is present;
+ QString full_filename;
+ videodev_driver m_driver;
+ int descriptor;
+
+//protected:
+#if defined(__linux__) && defined(ENABLE_AV)
+#ifdef V4L2_CAP_VIDEO_CAPTURE
+ struct v4l2_capability V4L2_capabilities;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_format fmt;
+ struct v4l2_fmtdesc fmtdesc; // Not sure if it must be here or inside detectPixelFormats(). Should inve
+// struct v4l2_input m_input;
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_querymenu querymenu;
+ void enumerateControls (void);
+ void enumerateMenu (void);
+#endif
+ struct video_capability V4L_capabilities;
+ struct video_buffer V4L_videobuffer;
+#endif
+ QVector<Kopete::AV::VideoInput> m_input;
+// QFile file;
+protected:
+ int currentwidth, minwidth, maxwidth, currentheight, minheight, maxheight;
+
+ QVector<rawbuffer> m_rawbuffers;
+ unsigned int m_streambuffers;
+ imagebuffer m_currentbuffer;
+ int m_buffer_size;
+
+ int m_current_input;
+ pixel_format m_pixelformat;
+
+ io_method m_io_method;
+ bool m_videocapture;
+ bool m_videochromakey;
+ bool m_videoscale;
+ bool m_videooverlay;
+ bool m_videoread;
+ bool m_videoasyncio;
+ bool m_videostream;
+
+ int xioctl(int request, void *arg);
+ int errnoReturn(const char* s);
+ int initRead();
+ int initMmap();
+ int initUserptr();
+
+ QString m_udi;
+};
+
+}
+
+}
+
+#endif
diff --git a/src/kvilib/ext/avdevice/videodevicemodelpool.cpp b/src/kvilib/ext/avdevice/videodevicemodelpool.cpp
new file mode 100644
index 000000000..3333beaae
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevicemodelpool.cpp
@@ -0,0 +1,94 @@
+//=============================================================================
+//
+// File : videodevicepool.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevicepool.cpp - Kopete Multiple Video Device handler Class
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#include "videodevicemodelpool.h"
+
+namespace Kopete {
+
+namespace AV {
+
+VideoDeviceModelPool::VideoDeviceModelPool()
+{
+}
+
+
+VideoDeviceModelPool::~VideoDeviceModelPool()
+{
+}
+
+void VideoDeviceModelPool::clear()
+{
+ m_devicemodel.clear();
+}
+
+size_t VideoDeviceModelPool::size()
+{
+ return m_devicemodel.size();
+}
+
+size_t VideoDeviceModelPool::addModel( QString newmodel )
+{
+ VideoDeviceModel newdevicemodel;
+ newdevicemodel.model=newmodel;
+ newdevicemodel.count=0;
+
+ if(m_devicemodel.size())
+ {
+ for ( int loop = 0 ; loop < m_devicemodel.size(); loop++)
+ if (newmodel == m_devicemodel[loop].model)
+ {
+ kDebug() << "Model " << newmodel << " already exists.";
+ m_devicemodel[loop].count++;
+ return m_devicemodel[loop].count;
+ }
+ }
+ m_devicemodel.push_back(newdevicemodel);
+ m_devicemodel[m_devicemodel.size()-1].model = newmodel;
+ m_devicemodel[m_devicemodel.size()-1].count = 0;
+ return 0;
+}
+
+
+}
+
+}
diff --git a/src/kvilib/ext/avdevice/videodevicemodelpool.h b/src/kvilib/ext/avdevice/videodevicemodelpool.h
new file mode 100644
index 000000000..56ede1a16
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevicemodelpool.h
@@ -0,0 +1,79 @@
+//=============================================================================
+//
+// File : videodevicepool.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevicepool.h - Kopete Multiple Video Device handler Class
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#ifndef KOPETE_AVVIDEODEVICEMODELPOOL_H
+#define KOPETE_AVVIDEODEVICEMODELPOOL_H
+
+#include <qstring.h>
+#include <qvector.h>
+#include <kdebug.h>
+#include "kopete_export.h"
+
+namespace Kopete {
+
+namespace AV {
+
+/**
+ @author Kopete Developers <kopete-devel@kde.org>
+*/
+class VideoDeviceModelPool{
+
+ struct VideoDeviceModel
+ {
+ QString model;
+ size_t count;
+ };
+ QVector<VideoDeviceModel> m_devicemodel;
+public:
+ VideoDeviceModelPool();
+ ~VideoDeviceModelPool();
+ void clear();
+ size_t size();
+ size_t addModel(QString newmodel);
+};
+
+}
+
+}
+
+#endif
diff --git a/src/kvilib/ext/avdevice/videodevicepool.cpp b/src/kvilib/ext/avdevice/videodevicepool.cpp
new file mode 100644
index 000000000..83271723c
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevicepool.cpp
@@ -0,0 +1,940 @@
+//=============================================================================
+//
+// File : videodevicepool.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevicepool.cpp - Kopete Video Device Low-level Support
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#define ENABLE_AV
+
+#include <assert.h>
+#include <cstdlib>
+#include <cerrno>
+#include <cstring>
+
+#include <klocale.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kconfiggroup.h>
+#include <qdir.h>
+
+#include "videodevice.h"
+#include "videodevicepool.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <solid/device.h>
+ #include <solid/devicenotifier.h>
+ #include <solid/deviceinterface.h>
+ #include <solid/video.h>
+#endif
+
+#define CLEAR(x) memset (&(x), 0, sizeof (x))
+
+namespace Kopete {
+
+namespace AV {
+
+VideoDevicePool *VideoDevicePool::s_self = NULL;
+__u64 VideoDevicePool::m_clients = 0;
+
+VideoDevicePool* VideoDevicePool::self()
+{
+// kDebug() << "libkopete (avdevice): self() called";
+ if (s_self == NULL)
+ {
+ s_self = new VideoDevicePool;
+ if (s_self)
+ m_clients = 0;
+ }
+// kDebug() << "libkopete (avdevice): self() exited successfuly";
+ return s_self;
+}
+
+VideoDevicePool::VideoDevicePool()
+: m_current_device(0)
+{
+#ifdef COMPILE_KDE_SUPPORT
+ connect( Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString&)), SLOT(deviceAdded(const QString &)) );
+ connect( Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString&)), SLOT(deviceRemoved(const QString &)) );
+#endif
+}
+
+
+VideoDevicePool::~VideoDevicePool()
+{
+}
+
+
+
+
+/*!
+ \fn VideoDevicePool::open()
+ */
+int VideoDevicePool::open()
+{
+ /// @todo implement me
+qDebug("VideoDevicePool::open()");
+ m_ready.lock();
+ if(!m_videodevice.size())
+ {
+ kDebug() << "open(): No devices found. Must scan for available devices." << m_current_device;
+ scanDevices();
+ }
+ if(!m_videodevice.size())
+ {
+ kDebug() << "open(): No devices found. bailing out." << m_current_device;
+ m_ready.unlock();
+ return EXIT_FAILURE;
+ }
+ if(m_current_device >= m_videodevice.size())
+ {
+ kDebug() << "open(): Device out of scope (" << m_current_device << "). Defaulting to the first one.";
+ m_current_device = 0;
+ }
+ int isopen = m_videodevice[currentDevice()].open();
+ if ( isopen == EXIT_SUCCESS)
+ {
+ loadConfig(); // Temporary hack. The open() seems to clean the input parameters. Need to find a way to fix it.
+
+ }
+ m_clients++;
+ kDebug() << "Number of clients: " << m_clients;
+ m_ready.unlock();
+ return isopen;
+}
+
+/*!
+ \fn VideoDevicePool::open(int device)
+ */
+int VideoDevicePool::open(int device)
+{
+ /// @todo implement me
+ kDebug() << "open(" << device << ") called.";
+ if(device >= m_videodevice.size())
+ {
+ kDebug() << "open(" << device <<"): Device does not exist.";
+ return EXIT_FAILURE;
+ }
+ close();
+ kDebug() << "open(" << device << ") Setting m_current_Device to " << device;
+ m_current_device = device;
+ kDebug() << "open(" << device << ") Calling open().";
+ saveConfig();
+
+ return open();
+}
+
+bool VideoDevicePool::isOpen()
+{
+ return m_videodevice[currentDevice()].isOpen();
+}
+
+/*!
+ \fn VideoDevicePool::showDeviceCapabilities(int device)
+ */
+int VideoDevicePool::showDeviceCapabilities(unsigned int device)
+{
+ return m_videodevice[device].showDeviceCapabilities();
+}
+
+int VideoDevicePool::width()
+{
+ return m_videodevice[currentDevice()].width();
+}
+
+int VideoDevicePool::minWidth()
+{
+ return m_videodevice[currentDevice()].minWidth();
+}
+
+int VideoDevicePool::maxWidth()
+{
+ return m_videodevice[currentDevice()].maxWidth();
+}
+
+int VideoDevicePool::height()
+{
+ return m_videodevice[currentDevice()].height();
+}
+
+int VideoDevicePool::minHeight()
+{
+ return m_videodevice[currentDevice()].minHeight();
+}
+
+int VideoDevicePool::maxHeight()
+{
+ return m_videodevice[currentDevice()].maxHeight();
+}
+
+int VideoDevicePool::setSize( int newwidth, int newheight)
+{
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].setSize(newwidth, newheight);
+ else
+ {
+ kDebug() << "VideoDevicePool::setSize() fallback for no device.";
+ m_buffer.width=newwidth;
+ m_buffer.height=newheight;
+ m_buffer.pixelformat= PIXELFORMAT_RGB24;
+ m_buffer.data.resize(m_buffer.width*m_buffer.height*3);
+ kDebug() << "VideoDevicePool::setSize() buffer size: "<< m_buffer.data.size();
+ }
+ return EXIT_SUCCESS;
+}
+
+/*!
+ \fn VideoDevicePool::close()
+ */
+int VideoDevicePool::close()
+{
+ /// @todo implement me
+ if(m_clients)
+ m_clients--;
+ if((currentDevice() < m_videodevice.size())&&(!m_clients))
+ return m_videodevice[currentDevice()].close();
+ if(m_clients)
+ kDebug() << "VideoDevicePool::close() The video device is still in use.";
+ if(currentDevice() >= m_videodevice.size())
+ kDebug() << "VideoDevicePool::close() Current device out of range.";
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn VideoDevicePool::startCapturing()
+ */
+int VideoDevicePool::startCapturing()
+{
+ kDebug() << "startCapturing() called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].startCapturing();
+ return EXIT_FAILURE;
+}
+
+
+/*!
+ \fn VideoDevicePool::stopCapturing()
+ */
+int VideoDevicePool::stopCapturing()
+{
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].stopCapturing();
+ return EXIT_FAILURE;
+}
+
+// Implementation of the methods that get / set input's adjustment parameters
+/*!
+ \fn VideoDevicePool::getBrightness()
+ */
+float VideoDevicePool::getBrightness()
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].getBrightness();
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::setBrightness(float brightness)
+ */
+float VideoDevicePool::setBrightness(float brightness)
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].setBrightness(brightness);
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::getContrast()
+ */
+float VideoDevicePool::getContrast()
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].getContrast();
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::setContrast(float contrast)
+ */
+float VideoDevicePool::setContrast(float contrast)
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].setContrast(contrast);
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::getSaturation()
+ */
+float VideoDevicePool::getSaturation()
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].getSaturation();
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::setSaturation(float saturation)
+ */
+float VideoDevicePool::setSaturation(float saturation)
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].setSaturation(saturation);
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::getWhiteness()
+ */
+float VideoDevicePool::getWhiteness()
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].getWhiteness();
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::setWhiteness(float whiteness)
+ */
+float VideoDevicePool::setWhiteness(float whiteness)
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].setWhiteness(whiteness);
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::getHue()
+ */
+float VideoDevicePool::getHue()
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].getHue();
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::setHue(float hue)
+ */
+float VideoDevicePool::setHue(float hue)
+{
+ if (currentDevice() < m_videodevice.size() )
+ return m_videodevice[currentDevice()].setHue(hue);
+ else
+ return 0;
+}
+
+/*!
+ \fn VideoDevicePool::getAutoBrightnessContrast()
+ */
+bool VideoDevicePool::getAutoBrightnessContrast()
+{
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].getAutoBrightnessContrast();
+ return false;
+}
+
+/*!
+ \fn VideoDevicePool::setAutoBrightnessContrast(bool brightnesscontrast)
+ */
+bool VideoDevicePool::setAutoBrightnessContrast(bool brightnesscontrast)
+{
+ kDebug() << "VideoDevicePool::setAutoBrightnessContrast(" << brightnesscontrast << ") called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].setAutoBrightnessContrast(brightnesscontrast);
+ return false;
+}
+
+/*!
+ \fn VideoDevicePool::getAutoColorCorrection()
+ */
+bool VideoDevicePool::getAutoColorCorrection()
+{
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].getAutoColorCorrection();
+ return false;
+}
+
+/*!
+ \fn VideoDevicePool::setAutoColorCorrection(bool colorcorrection)
+ */
+bool VideoDevicePool::setAutoColorCorrection(bool colorcorrection)
+{
+ kDebug() << "VideoDevicePool::setAutoColorCorrection(" << colorcorrection << ") called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].setAutoColorCorrection(colorcorrection);
+ return false;
+}
+
+/*!
+ \fn VideoDevicePool::getIMageAsMirror()
+ */
+bool VideoDevicePool::getImageAsMirror()
+{
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].getImageAsMirror();
+ return false;
+}
+
+/*!
+ \fn VideoDevicePool::setImageAsMirror(bool imageasmirror)
+ */
+bool VideoDevicePool::setImageAsMirror(bool imageasmirror)
+{
+ kDebug() << "VideoDevicePool::setImageAsMirror(" << imageasmirror << ") called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].setImageAsMirror(imageasmirror);
+ return false;
+}
+
+/*!
+ \fn VideoDevicePool::getFrame()
+ */
+int VideoDevicePool::getFrame()
+{
+// kDebug() << "VideoDevicePool::getFrame() called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].getFrame();
+ else
+ {
+ kDebug() << "VideoDevicePool::getFrame() fallback for no device.";
+ for(int loop=0; loop < m_buffer.data.size(); loop+=3)
+ {
+ m_buffer.data[loop] = 255;
+ m_buffer.data[loop+1] = 0;
+ m_buffer.data[loop+2] = 0;
+ }
+ }
+ kDebug() << "VideoDevicePool::getFrame() exited successfuly.";
+
+ return EXIT_SUCCESS;
+}
+
+/*!
+ \fn VideoDevicePool::getQImage(QImage *qimage)
+ */
+int VideoDevicePool::getImage(QImage *qimage)
+{
+// kDebug() << "VideoDevicePool::getImage() called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].getImage(qimage);
+ else
+ {
+ kDebug() << "VideoDevicePool::getImage() fallback for no device.";
+
+ // do NOT delete qimage here, as it is received as a parameter
+ if (qimage->width() != width() || qimage->height() != height())
+ *qimage = QImage(width(), height(), QImage::Format_RGB32);
+
+ uchar *bits=qimage->bits();
+ switch(m_buffer.pixelformat)
+ {
+ case PIXELFORMAT_NONE : break;
+ case PIXELFORMAT_GREY : break;
+ case PIXELFORMAT_RGB332 : break;
+ case PIXELFORMAT_RGB555 : break;
+ case PIXELFORMAT_RGB555X: break;
+ case PIXELFORMAT_RGB565 : break;
+ case PIXELFORMAT_RGB565X: break;
+ case PIXELFORMAT_RGB24 :
+ {
+ kDebug() << "VideoDevicePool::getImage() fallback for no device - RGB24.";
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = m_buffer.data[step];
+ bits[loop+1] = m_buffer.data[step+1];
+ bits[loop+2] = m_buffer.data[step+2];
+ bits[loop+3] = 255;
+ step+=3;
+ }
+ }
+ break;
+ case PIXELFORMAT_BGR24 : break;
+ {
+ int step=0;
+ for(int loop=0;loop < qimage->numBytes();loop+=4)
+ {
+ bits[loop] = m_buffer.data[step+2];
+ bits[loop+1] = m_buffer.data[step+1];
+ bits[loop+2] = m_buffer.data[step];
+ bits[loop+3] = 255;
+ step+=3;
+ }
+ }
+ break;
+ case PIXELFORMAT_RGB32 : memcpy(bits,&m_buffer.data[0], m_buffer.data.size());
+ break;
+ case PIXELFORMAT_BGR32 : break;
+ case PIXELFORMAT_YUYV : break;
+ case PIXELFORMAT_UYVY : break;
+ case PIXELFORMAT_YUV420P: break;
+ case PIXELFORMAT_YUV422P: break;
+ default: break;
+ }
+ }
+ kDebug() << "VideoDevicePool::getImage() exited successfuly.";
+ return EXIT_SUCCESS;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::selectInput(int input)
+ */
+int VideoDevicePool::selectInput(int newinput)
+{
+ kDebug() << "VideoDevicePool::selectInput(" << newinput << ") called.";
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].selectInput(newinput);
+ else
+ return 0;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::setInputParameters()
+ */
+int VideoDevicePool::setInputParameters()
+{
+ if(m_videodevice.size())
+ return m_videodevice[currentDevice()].setInputParameters();
+ else
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::fillDeviceQComboBox(QComboBox *combobox)
+ */
+int VideoDevicePool::fillDeviceQComboBox(QComboBox *combobox)
+{
+ /// @todo implement me
+ kDebug() << "Called.";
+// check if QComboBox is a valid pointer.
+ if (combobox != NULL)
+ {
+ combobox->clear();
+ kDebug() << "Combobox cleaned.";
+ if(m_videodevice.size())
+ {
+ for (int loop=0; loop < m_videodevice.size(); loop++)
+ {
+ combobox->addItem(m_videodevice[loop].m_name);
+ kDebug() << "Added device " << loop << ": " << m_videodevice[loop].m_name;
+ }
+ combobox->setCurrentIndex(currentDevice());
+ return EXIT_SUCCESS;
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::fillInputQComboBox(QComboBox *combobox)
+ */
+int VideoDevicePool::fillInputQComboBox(QComboBox *combobox)
+{
+ /// @todo implement me
+ kDebug() << "Called.";
+ if (combobox != NULL)
+ {
+ combobox->clear();
+ if ( !m_videodevice.isEmpty() && (currentDevice()>=0) && currentDevice() < m_videodevice.size() )
+ {
+ if(m_videodevice[currentDevice()].inputs()>0)
+ {
+ for (int loop=0; loop < m_videodevice[currentDevice()].inputs(); loop++)
+ {
+ combobox->addItem(m_videodevice[currentDevice()].m_input[loop].name);
+ kDebug() << "Added input " << loop << ": " << m_videodevice[currentDevice()].m_input[loop].name << " (tuner: " << m_videodevice[currentDevice()].m_input[loop].hastuner << ")";
+ }
+ combobox->setCurrentIndex(currentInput());
+ return EXIT_SUCCESS;
+ }
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::fillStandardQComboBox(QComboBox *combobox)
+ */
+int VideoDevicePool::fillStandardQComboBox(QComboBox *combobox)
+{
+ /// @todo implement me
+ kDebug() << "Called.";
+ if (combobox != NULL)
+ {
+ combobox->clear();
+ if ( !m_videodevice.isEmpty() && currentDevice() < m_videodevice.size() )
+ {
+ if(m_videodevice[currentDevice()].inputs()>0)
+ {
+ for (unsigned int loop=0; loop < 25; loop++)
+ {
+ if ( (m_videodevice[currentDevice()].m_input[currentInput()].m_standards) & (1 << loop) )
+ combobox->addItem(m_videodevice[currentDevice()].signalStandardName( 1 << loop));
+/*
+ case STANDARD_PAL_B1 : return V4L2_STD_PAL_B1; break;
+ case STANDARD_PAL_G : return V4L2_STD_PAL_G; break;
+ case STANDARD_PAL_H : return V4L2_STD_PAL_H; break;
+ case STANDARD_PAL_I : return V4L2_STD_PAL_I; break;
+ case STANDARD_PAL_D : return V4L2_STD_PAL_D; break;
+ case STANDARD_PAL_D1 : return V4L2_STD_PAL_D1; break;
+ case STANDARD_PAL_K : return V4L2_STD_PAL_K; break;
+ case STANDARD_PAL_M : return V4L2_STD_PAL_M; break;
+ case STANDARD_PAL_N : return V4L2_STD_PAL_N; break;
+ case STANDARD_PAL_Nc : return V4L2_STD_PAL_Nc; break;
+ case STANDARD_PAL_60 : return V4L2_STD_PAL_60; break;
+ case STANDARD_NTSC_M : return V4L2_STD_NTSC_M; break;
+ case STANDARD_NTSC_M_JP : return V4L2_STD_NTSC_M_JP; break;
+ case STANDARD_NTSC_443 : return V4L2_STD_NTSC; break; // Using workaround value because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id
+ case STANDARD_SECAM_B : return V4L2_STD_SECAM_B; break;
+ case STANDARD_SECAM_D : return V4L2_STD_SECAM_D; break;
+ case STANDARD_SECAM_G : return V4L2_STD_SECAM_G; break;
+ case STANDARD_SECAM_H : return V4L2_STD_SECAM_H; break;
+ case STANDARD_SECAM_K : return V4L2_STD_SECAM_K; break;
+ case STANDARD_SECAM_K1 : return V4L2_STD_SECAM_K1; break;
+ case STANDARD_SECAM_L : return V4L2_STD_SECAM_L; break;
+ case STANDARD_SECAM_LC : return V4L2_STD_SECAM; break; // Using workaround value because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id
+ case STANDARD_ATSC_8_VSB : return V4L2_STD_ATSC_8_VSB; break; // ATSC/HDTV Standard officially not supported by V4L2 but exists in videodev2.h
+ case STANDARD_ATSC_16_VSB : return V4L2_STD_ATSC_16_VSB; break; // ATSC/HDTV Standard officially not supported by V4L2 but exists in videodev2.h
+ case STANDARD_PAL_BG : return V4L2_STD_PAL_BG; break;
+ case STANDARD_PAL_DK : return V4L2_STD_PAL_DK; break;
+ case STANDARD_PAL : return V4L2_STD_PAL; break;
+ case STANDARD_NTSC : return V4L2_STD_NTSC; break;
+ case STANDARD_SECAM_DK : return V4L2_STD_SECAM_DK; break;
+ case STANDARD_SECAM : return V4L2_STD_SECAM; break;
+ case STANDARD_525_60 : return V4L2_STD_525_60; break;
+ case STANDARD_625_50 : return V4L2_STD_625_50; break;
+ case STANDARD_ALL : return V4L2_STD_ALL; break;
+
+ combobox->insertItem(m_videodevice[currentDevice()].m_input[loop].name);
+ kDebug() << "StandardQComboBox: Added input " << loop << ": " << m_videodevice[currentDevice()].m_input[loop].name << " (tuner: " << m_videodevice[currentDevice()].m_input[loop].hastuner << ")";*/
+ }
+ combobox->setCurrentIndex(currentInput());
+ return EXIT_SUCCESS;
+ }
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::scanDevices()
+ */
+int VideoDevicePool::scanDevices()
+{
+ /// @todo implement me
+
+ kDebug() << "called";
+#ifdef COMPILE_KDE_SUPPORT
+ foreach (Solid::Device device,
+ Solid::Device::listFromType(Solid::DeviceInterface::Video, QString())) {
+ registerDevice( device );
+ }
+
+#endif
+ kDebug() << "exited successfuly";
+ return EXIT_SUCCESS;
+}
+
+#ifdef COMPILE_KDE_SUPPORT
+
+void VideoDevicePool::registerDevice( Solid::Device & device )
+{
+ kDebug() << "New video device at " << device.udi();
+ const Solid::Device * vendorDevice = &device;
+ while ( vendorDevice->isValid() && vendorDevice->vendor().isEmpty() )
+ {
+ vendorDevice = new Solid::Device( vendorDevice->parentUdi() );
+ }
+ if ( vendorDevice->isValid() )
+ {
+ kDebug() << "vendor: " << vendorDevice->vendor() << ", product: " << vendorDevice->product();
+ }
+ Solid::Video * solidVideoDevice = device.as<Solid::Video>();
+ if ( solidVideoDevice ) {
+ QStringList protocols = solidVideoDevice->supportedProtocols();
+ if ( protocols.contains( "video4linux" ) )
+ {
+ QStringList drivers = solidVideoDevice->supportedDrivers( "video4linux" );
+ if ( drivers.contains( "video4linux" ) )
+ {
+ kDebug() << "V4L device path is" << solidVideoDevice->driverHandle( "video4linux" ).toString();
+ VideoDevice videodevice;
+ videodevice.setUdi( device.udi() );
+ videodevice.setFileName(solidVideoDevice->driverHandle( "video4linux" ).toString());
+ kDebug() << "Found device " << videodevice.full_filename;
+ videodevice.open();
+ if(videodevice.isOpen())
+ {
+ kDebug() << "File " << videodevice.full_filename << " was opened successfuly";
+ videodevice.close();
+ videodevice.m_modelindex=m_modelvector.addModel (videodevice.m_model); // Adds device to the device list and sets model number
+ m_videodevice.push_back(videodevice);
+ }
+ }
+ }
+ }
+}
+#endif
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::hasDevices()
+ */
+bool VideoDevicePool::hasDevices()
+{
+ /// @todo implement me
+ if(m_videodevice.size())
+ return true;
+ return false;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::size()
+ */
+size_t VideoDevicePool::size()
+{
+ /// @todo implement me
+ return m_videodevice.size();
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::currentDevice()
+ */
+int VideoDevicePool::currentDevice()
+{
+ /// @todo implement me
+ return m_current_device;
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::currentInput()
+ */
+int VideoDevicePool::currentInput()
+{
+ /// @todo implement me
+ return m_videodevice[currentDevice()].currentInput();
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::currentInput()
+ */
+unsigned int VideoDevicePool::inputs()
+{
+ /// @todo implement me
+ return m_videodevice[currentDevice()].inputs();
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::loadConfig()
+ */
+void VideoDevicePool::loadConfig()
+{
+ /// @todo implement me
+ kDebug() << "called";
+ if((hasDevices())&&(m_clients==0))
+ {
+ KConfigGroup config(KGlobal::config(), "Video Device Settings");
+ QString currentdevice = config.readEntry("Current Device", QString());
+ kDebug() << "Current device: " << currentdevice;
+
+// m_current_device = 0; // Must check this thing because of the fact that multiple loadConfig in other methodas can do bad things. Watch out!
+
+ VideoDeviceVector::iterator vditerator;
+ for( vditerator = m_videodevice.begin(); vditerator != m_videodevice.end(); ++vditerator )
+ {
+ const QString modelindex = QString::fromLocal8Bit ( "Model %1 Device %2") .arg ((*vditerator).m_name ) .arg ((*vditerator).m_modelindex);
+ if(modelindex == currentdevice)
+ {
+ m_current_device = std::distance (m_videodevice.begin(), vditerator);
+// kDebug() << "This place will be used to set " << modelindex << " as the current device ( " << std::distance(m_videodevice.begin(), vditerator ) << " ).";
+ }
+ const QString name = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Name") .arg ((*vditerator).m_name ) .arg ((*vditerator).m_modelindex)), (*vditerator).m_model);
+ const int currentinput = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Current input") .arg ((*vditerator).m_name ) .arg ((*vditerator).m_modelindex)), 0);
+ kDebug() << "Device name: " << name;
+ kDebug() << "Device current input: " << currentinput;
+ (*vditerator).selectInput(currentinput);
+
+ for (int input = 0 ; input < (*vditerator).m_input.size(); input++)
+ {
+ const float brightness = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Brightness").arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 );
+ const float contrast = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Contrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 );
+ const float saturation = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Saturation").arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 );
+ const float whiteness = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Whiteness") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 );
+ const float hue = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Hue") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 );
+ const bool autobrightnesscontrast = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoBrightnessContrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , false );
+ const bool autocolorcorrection = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoColorCorrection") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , false );
+ const bool imageasmirror = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 mageAsMirror") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , false );
+ (*vditerator).setBrightness(brightness);
+ (*vditerator).setContrast(contrast);
+ (*vditerator).setSaturation(saturation);
+ (*vditerator).setHue(hue);
+ (*vditerator).setAutoBrightnessContrast(autobrightnesscontrast);
+ (*vditerator).setAutoColorCorrection(autocolorcorrection);
+ (*vditerator).setImageAsMirror(imageasmirror);
+ kDebug() << "Brightness:" << brightness;
+ kDebug() << "Contrast :" << contrast;
+ kDebug() << "Saturation:" << saturation;
+ kDebug() << "Whiteness :" << whiteness;
+ kDebug() << "Hue :" << hue;
+ kDebug() << "AutoBrightnessContrast:" << autobrightnesscontrast;
+ kDebug() << "AutoColorCorrection :" << autocolorcorrection;
+ kDebug() << "ImageAsMirror :" << imageasmirror;
+ }
+ }
+ }
+}
+
+/*!
+ \fn Kopete::AV::VideoDevicePool::saveConfig()
+ */
+void VideoDevicePool::saveConfig()
+{
+ /// @todo implement me
+ kDebug() << "called";
+ if(hasDevices())
+ {
+ KConfigGroup config(KGlobal::config(), "Video Device Settings");
+
+/* if(m_modelvector.size())
+ {
+ VideoDeviceModelPool::m_devicemodel::iterator vmiterator;
+ for( vmiterator = m_modelvector.begin(); vmiterator != m_modelvector.end(); ++vmiterator )
+ {
+ kDebug() << "Device Model: " << (*vmiterator).name;
+ kDebug() << "Device Count: " << (*vmiterator).count;
+ }
+ }
+*/
+// Stores what is the current video device in use
+ const QString currentdevice = QString::fromLocal8Bit ( "Model %1 Device %2" ) .arg(m_videodevice[m_current_device].m_model) .arg(m_videodevice[m_current_device].m_modelindex);
+ config.writeEntry( "Current Device", currentdevice);
+
+ VideoDeviceVector::iterator vditerator;
+ for( vditerator = m_videodevice.begin(); vditerator != m_videodevice.end(); ++vditerator )
+ {
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Name:" << (*vditerator).m_name;
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Current input:" << (*vditerator).currentInput();
+
+// Stores current input for the given video device
+ const QString name = QString::fromLocal8Bit ( "Model %1 Device %2 Name") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex);
+ const QString currentinput = QString::fromLocal8Bit ( "Model %1 Device %2 Current input") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex);
+ config.writeEntry( name, (*vditerator).m_name);
+ config.writeEntry( currentinput, (*vditerator).currentInput());
+
+ for (int input = 0 ; input < (*vditerator).m_input.size(); input++)
+ {
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Brightness: " << (*vditerator).m_input[input].getBrightness();
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Contrast : " << (*vditerator).m_input[input].getContrast();
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Saturation: " << (*vditerator).m_input[input].getSaturation();
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Whiteness : " << (*vditerator).m_input[input].getWhiteness();
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Hue : " << (*vditerator).m_input[input].getHue();
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Automatic brightness / contrast: " << (*vditerator).m_input[input].getAutoBrightnessContrast();
+ kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Automatic color correction : " << (*vditerator).m_input[input].getAutoColorCorrection();
+
+// Stores configuration about each channel
+ const QString brightness = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Brightness") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString contrast = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Contrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString saturation = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Saturation") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString whiteness = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Whiteness") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString hue = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Hue") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString autobrightnesscontrast = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoBrightnessContrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString autocolorcorrection = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoColorCorrection") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ const QString imageasmirror = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 ImageAsMirror") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input);
+ config.writeEntry( brightness, (double)(*vditerator).m_input[input].getBrightness());
+ config.writeEntry( contrast, (double)(*vditerator).m_input[input].getContrast());
+ config.writeEntry( saturation, (double)(*vditerator).m_input[input].getSaturation());
+ config.writeEntry( whiteness, (double)(*vditerator).m_input[input].getWhiteness());
+ config.writeEntry( hue, (double)(*vditerator).m_input[input].getHue());
+ config.writeEntry( autobrightnesscontrast, (*vditerator).m_input[input].getAutoBrightnessContrast());
+ config.writeEntry( autocolorcorrection, (*vditerator).m_input[input].getAutoColorCorrection());
+ config.writeEntry( imageasmirror, (*vditerator).m_input[input].getImageAsMirror());
+ }
+ }
+ config.sync();
+ kDebug();
+ }
+}
+
+#ifdef COMPILE_KDE_SUPPORT
+
+void VideoDevicePool::deviceAdded( const QString & udi )
+{
+ kDebug() << "("<< udi << ") called";
+ Solid::Device dev( udi );
+ if ( dev.is<Solid::Video>() )
+ {
+ registerDevice( dev );
+ emit deviceRegistered( udi );
+ }
+}
+
+void VideoDevicePool::deviceRemoved( const QString & udi )
+{
+ kDebug() << "("<< udi << ") called";
+ int i = 0;
+ foreach ( VideoDevice vd, m_videodevice )
+ {
+ if ( vd.udi() == udi )
+ {
+ kDebug() << "Video device '" << udi << "' has been removed!";
+ emit deviceUnregistered( udi );
+ // not sure if this is safe but at this point the device node is gone already anyway
+ m_videodevice.remove( i );
+ }
+ else
+ {
+ i++;
+ }
+ }
+}
+
+#endif
+
+} // namespace AV
+
+} // namespace Kopete
diff --git a/src/kvilib/ext/avdevice/videodevicepool.h b/src/kvilib/ext/avdevice/videodevicepool.h
new file mode 100644
index 000000000..2adc663b5
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevicepool.h
@@ -0,0 +1,175 @@
+//=============================================================================
+//
+// File : videodevicepool.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevicepool.h - Kopete Multiple Video Device handler Class
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#ifndef VIDEODEVICEPOOL_H
+#define VIDEODEVICEPOOL_H
+
+#include <iostream>
+
+#include "kvi_settings.h"
+
+#include "videoinput.h"
+#include "videodevicemodelpool.h"
+#include <qstring.h>
+#include <qimage.h>
+#include <q3valuevector.h>
+#include <qmutex.h>
+#include <QComboBox>
+#include "videodevice.h"
+#include "kopete_export.h"
+#include <kconfig.h>
+#include <kglobal.h>
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <solid/device.h>
+#endif
+
+// Uncomment this line and comment out the include and using lines to
+// revert to standard vector if you hit issues. It should all be fine though.
+// typedef QVector<Kopete::AV::VideoDevice> VideoDeviceVector;
+#include "videodevicevector.h"
+using Kopete::AV::VideoDeviceVector;
+
+namespace Kopete {
+
+namespace AV {
+
+/**
+This class allows kopete to check for the existence, open, configure, test, set parameters, grab frames from and close a given video capture card using the Video4Linux API.
+
+@author Cláudio da Silveira Pinheiro
+*/
+
+class KOPETE_EXPORT VideoDevicePool : public QObject
+{
+Q_OBJECT
+public:
+ static VideoDevicePool* self();
+ int open();
+ int open(int device);
+ bool isOpen();
+ int getFrame();
+ int width();
+ int minWidth();
+ int maxWidth();
+ int height();
+ int minHeight();
+ int maxHeight();
+ int setSize( int newwidth, int newheight);
+ int close();
+ int startCapturing();
+ int stopCapturing();
+ int readFrame();
+ int getImage(QImage *qimage);
+ int selectInput(int newinput);
+ int setInputParameters();
+ int scanDevices();
+#ifdef COMPILE_KDE_SUPPORT
+ void registerDevice( Solid::Device & dev );
+#endif
+ bool hasDevices();
+ size_t size();
+ ~VideoDevicePool();
+ VideoDeviceVector m_videodevice; // Vector to be filled with found devices
+ VideoDeviceModelPool m_modelvector; // Vector to be filled with unique device models
+ int fillDeviceQComboBox(QComboBox *combobox);
+ int fillInputQComboBox(QComboBox *combobox);
+ int fillStandardQComboBox(QComboBox *combobox);
+ int currentDevice();
+ int currentInput();
+ unsigned int inputs();
+
+ float getBrightness();
+ float setBrightness(float brightness);
+ float getContrast();
+ float setContrast(float contrast);
+ float getSaturation();
+ float setSaturation(float saturation);
+ float getWhiteness();
+ float setWhiteness(float whiteness);
+ float getHue();
+ float setHue(float hue);
+
+ bool getAutoBrightnessContrast();
+ bool setAutoBrightnessContrast(bool brightnesscontrast);
+ bool getAutoColorCorrection();
+ bool setAutoColorCorrection(bool colorcorrection);
+ bool getImageAsMirror();
+ bool setImageAsMirror(bool imageasmirror);
+
+ void loadConfig(); // Load configuration parameters;
+ void saveConfig(); // Save configuretion parameters;
+signals:
+ /**
+ * Provisional signatures, probably more useful to indicate which device was registered
+ */
+ void deviceRegistered( const QString & udi );
+ void deviceUnregistered( const QString & udi );
+#ifdef COMPILE_KDE_SUPPORT
+protected slots:
+ /**
+ * Slot called when a new device is added to the system
+ */
+ void deviceAdded( const QString & udi );
+ void deviceRemoved( const QString & udi );
+#endif
+protected:
+ int xioctl(int request, void *arg);
+ int errnoReturn(const char* s);
+ int showDeviceCapabilities(unsigned int device);
+ void guessDriver();
+ int m_current_device;
+ struct imagebuffer m_buffer; // only used when no devices were found
+
+ QMutex m_ready;
+private:
+ VideoDevicePool();
+ static VideoDevicePool* s_self;
+ static __u64 m_clients; // Number of instances
+};
+
+}
+
+}
+
+#endif // VIDEODEVICEPOOL_H
diff --git a/src/kvilib/ext/avdevice/videodevicevector.cpp b/src/kvilib/ext/avdevice/videodevicevector.cpp
new file mode 100644
index 000000000..4edc96c39
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevicevector.cpp
@@ -0,0 +1,88 @@
+//=============================================================================
+//
+// File : videodevicevector.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevicevector.cpp - Kopete Video Device List Abstration
+
+ Copyright (c) 2009 by Alan Jones <skyphyr@gmail.com>
+
+ Kopete (c) 2002-2009 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 3 of the License, or (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ *************************************************************************
+*/
+
+#include "videodevicevector.h"
+
+namespace Kopete {
+
+namespace AV {
+
+VideoDevice& VideoDeviceVector::operator[] (int i)
+ {
+ if (i>=size())
+ {
+ //we're outside the range so let's return a default camera not available VideoDevice
+ return fallback;
+ }
+
+ //if we've made it here then we're within range
+ return QVector<VideoDevice>::operator[](i);
+ }
+
+const VideoDevice& VideoDeviceVector::operator[] (int i) const
+ {
+ return at(i);
+ }
+
+const VideoDevice& VideoDeviceVector::at(int i) const
+ {
+ if (i>=size())
+ {
+ //we're outside the range so let's return a default camera not available VideoDevice
+ return fallback;
+ }
+
+ //if we've made it here then we're within range
+ return QVector<VideoDevice>::operator[](i);
+ }
+
+}
+
+}
diff --git a/src/kvilib/ext/avdevice/videodevicevector.h b/src/kvilib/ext/avdevice/videodevicevector.h
new file mode 100644
index 000000000..e8bd330ac
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videodevicevector.h
@@ -0,0 +1,89 @@
+//=============================================================================
+//
+// File : videodevicevector.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videodevicevector.h - Kopete Video Device List Abstration
+
+ Copyright (c) 2009 by Alan Jones <skyphyr@gmail.com>
+
+ Kopete (c) 2002-2009 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 3 of the License, or (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ *************************************************************************
+*/
+
+#ifndef KOPETE_AVVIDEODEVICEVECTOR_H
+#define KOPETE_AVVIDEODEVICEVECTOR_H
+
+#include "videodevice.h"
+#include "dummyvideodevice.h"
+
+namespace Kopete {
+
+namespace AV {
+
+/**
+@author Kopete Developers
+*/
+
+class VideoDeviceVector : public QVector<VideoDevice>
+{
+
+public:
+ VideoDeviceVector() {}
+ ~VideoDeviceVector() {}
+
+ VideoDevice& operator[] (int i);
+
+ const VideoDevice& operator[] (int i) const;
+
+ const VideoDevice& at(int i) const;
+
+private:
+
+ DummyVideoDevice fallback;
+};
+
+}
+
+}
+
+
+
+#endif
diff --git a/src/kvilib/ext/avdevice/videoinput.cpp b/src/kvilib/ext/avdevice/videoinput.cpp
new file mode 100644
index 000000000..2f95c8d58
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videoinput.cpp
@@ -0,0 +1,198 @@
+//=============================================================================
+//
+// File : videoinput.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videoinput.cpp - Kopete Video Input Class
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#include "videoinput.h"
+
+namespace Kopete {
+
+namespace AV {
+
+VideoInput::VideoInput()
+{
+ kDebug() << "Executing Video Input's constructor!!!";
+ m_brightness = 0.5;
+ m_contrast = 0.5;
+ m_saturation = 0.5;
+ m_hue = 0.5;
+ m_autobrightnesscontrast = false;
+ m_autocolorcorrection = false;
+}
+
+
+VideoInput::~VideoInput()
+{
+}
+
+float VideoInput::getBrightness()
+{
+// kDebug() << " called.";
+ return m_brightness;
+}
+
+float VideoInput::setBrightness(float brightness)
+{
+// kDebug() << " called.";
+ if ( brightness > 1 )
+ brightness = 1;
+ else
+ if ( brightness < 0 )
+ brightness = 0;
+ m_brightness = brightness;
+ return getBrightness();
+}
+
+float VideoInput::getContrast()
+{
+// kDebug() << " called.";
+ return m_contrast;
+}
+
+float VideoInput::setContrast(float contrast)
+{
+// kDebug() << " called.";
+ if ( contrast > 1 )
+ contrast = 1;
+ else
+ if ( contrast < 0 )
+ contrast = 0;
+ m_contrast = contrast;
+ return getContrast();
+}
+
+float VideoInput::getSaturation()
+{
+// kDebug() << " called.";
+ return m_saturation;
+}
+
+float VideoInput::setSaturation(float saturation)
+{
+// kDebug() << " called.";
+ if ( saturation > 1 )
+ saturation = 1;
+ else
+ if ( saturation < 0 )
+ saturation = 0;
+ m_saturation = saturation;
+ return getSaturation();
+}
+
+float VideoInput::getWhiteness()
+{
+// kDebug() << " called.";
+ return m_whiteness;
+}
+
+float VideoInput::setWhiteness(float whiteness)
+{
+// kDebug() << " called.";
+ if ( whiteness > 1 )
+ whiteness = 1;
+ else
+ if ( whiteness < 0 )
+ whiteness = 0;
+ m_whiteness = whiteness;
+ return getWhiteness();
+}
+
+float VideoInput::getHue()
+{
+// kDebug() << " called.";
+ return m_hue;
+}
+
+float VideoInput::setHue(float hue)
+{
+// kDebug() << " called.";
+ if ( hue > 1 )
+ hue = 1;
+ else
+ if ( hue < 0 )
+ hue = 0;
+ m_hue = hue;
+ return getHue();
+}
+
+
+bool VideoInput::getAutoBrightnessContrast()
+{
+// kDebug() << " called.";
+ return m_autobrightnesscontrast;
+}
+
+bool VideoInput::setAutoBrightnessContrast(bool brightnesscontrast)
+{
+// kDebug() << " called.";
+ m_autobrightnesscontrast = brightnesscontrast;
+ return getAutoBrightnessContrast();
+}
+
+bool VideoInput::getAutoColorCorrection()
+{
+// kDebug() << " called.";
+ return m_autocolorcorrection;
+}
+
+bool VideoInput::setAutoColorCorrection(bool colorcorrection)
+{
+// kDebug() << " called.";
+ m_autocolorcorrection = colorcorrection;
+ return getAutoColorCorrection();
+}
+
+bool VideoInput::getImageAsMirror()
+{
+// kDebug() << " called.";
+ return m_imageasmirror;
+}
+
+bool VideoInput::setImageAsMirror(bool imageasmirror)
+{
+// kDebug() << " called.";
+ m_imageasmirror = imageasmirror;
+ return getImageAsMirror();
+}
+
+}
+
+}
diff --git a/src/kvilib/ext/avdevice/videoinput.h b/src/kvilib/ext/avdevice/videoinput.h
new file mode 100644
index 000000000..fcb4970dd
--- /dev/null
+++ b/src/kvilib/ext/avdevice/videoinput.h
@@ -0,0 +1,111 @@
+//=============================================================================
+//
+// File : videoinput.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// This file has been taken from the "Kopete, The KDE Instant Messenger"
+// sourcecode. Original copyright of the file follows:
+//=============================================================================
+
+/*
+ videoinput.h - Kopete Video Input Class
+
+ Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro <taupter@gmail.com>
+
+ Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#define ENABLE_AV
+
+#ifndef KOPETE_AVVIDEOINPUT_H
+#define KOPETE_AVVIDEOINPUT_H
+
+#ifdef __linux__
+#include <asm/types.h>
+#undef __STRICT_ANSI__
+#endif // __linux__
+#ifndef __u64 //required by videodev.h
+#define __u64 unsigned long long
+#endif // __u64*/
+
+#include <qstring.h>
+#include <kdebug.h>
+#include "kopete_export.h"
+
+namespace Kopete {
+
+namespace AV {
+
+/**
+@author Kopete Developers
+*/
+class KOPETE_EXPORT VideoInput{
+public:
+ VideoInput();
+ ~VideoInput();
+ QString name;
+ int hastuner;
+ __u64 m_standards;
+ float getBrightness();
+ float setBrightness(float brightness);
+ float getContrast();
+ float setContrast(float contrast);
+ float getSaturation();
+ float setSaturation(float saturation);
+ float getWhiteness();
+ float setWhiteness(float whiteness);
+ float getHue();
+ float setHue(float Hue);
+ bool getAutoBrightnessContrast();
+ bool setAutoBrightnessContrast(bool brightnesscontrast);
+ bool getAutoColorCorrection();
+ bool setAutoColorCorrection(bool colorcorrection);
+ bool getImageAsMirror();
+ bool setImageAsMirror(bool imageasmirror);
+
+protected:
+// this block must be changed to use a vector of controls instead of fixed ones
+ float m_brightness;
+ float m_contrast;
+ float m_saturation;
+ float m_whiteness;
+ float m_hue;
+
+ bool m_autobrightnesscontrast;
+ bool m_autocolorcorrection;
+ bool m_imageasmirror;
+
+
+};
+
+}
+
+}
+
+#endif
diff --git a/src/kvirc/kernel/kvi_options.cpp b/src/kvirc/kernel/kvi_options.cpp
index 25778480a..06ad5dcbc 100644
--- a/src/kvirc/kernel/kvi_options.cpp
+++ b/src/kvirc/kernel/kvi_options.cpp
@@ -315,7 +315,10 @@ KviBoolOption g_boolOptionsTable[KVI_NUM_BOOL_OPTIONS]=
BOOL_OPTION("PasteLastLogOnQueryJoin",false,KviOption_sectFlagLogging),
BOOL_OPTION("UseSpecifiedSmartColorForOwnNick",false,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
BOOL_OPTION("UseFullWordHighlighting",false,KviOption_sectFlagIrcView),
- BOOL_OPTION("ZshLikeNickCompletion",false,KviOption_sectFlagInput)
+ BOOL_OPTION("ZshLikeNickCompletion",false,KviOption_sectFlagInput),
+ BOOL_OPTION("AutoAcceptDccVideo", false, KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccVideo", false, KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccVideoWhenAutoAccepted",true,KviOption_sectFlagDcc)
};
#define STRING_OPTION(_txt,_val,_flags) KviStringOption(KVI_STRING_OPTIONS_PREFIX _txt,_val,_flags)
diff --git a/src/kvirc/kernel/kvi_options.h b/src/kvirc/kernel/kvi_options.h
index 2a803e183..7330ea0c9 100644
--- a/src/kvirc/kernel/kvi_options.h
+++ b/src/kvirc/kernel/kvi_options.h
@@ -323,8 +323,11 @@ DECLARE_OPTION_STRUCT(KviStringListOption,QStringList)
#define KviOption_boolUseSpecifiedSmartColorForOwnNick 229 /* interface::ircview */
#define KviOption_boolUseFullWordHighlighting 230 /* highlight */
#define KviOption_boolZshLikeNickCompletion 231
+#define KviOption_boolAutoAcceptDccVideo 232 /* dcc::video */
+#define KviOption_boolCreateMinimizedDccVideo 233 /* dcc::video */
+#define KviOption_boolCreateMinimizedDccVideoWhenAutoAccepted 234 /* dcc::video */
-#define KVI_NUM_BOOL_OPTIONS 232
+#define KVI_NUM_BOOL_OPTIONS 235
#define KVI_STRING_OPTIONS_PREFIX "string"
diff --git a/src/modules/dcc/CMakeLists.txt b/src/modules/dcc/CMakeLists.txt
index 71da80ff6..c380cb998 100644
--- a/src/modules/dcc/CMakeLists.txt
+++ b/src/modules/dcc/CMakeLists.txt
@@ -6,6 +6,7 @@ SET(kvidcc_MOC_HDRS
dialogs.h
marshal.h
send.h
+ video.h
voice.h
window.h
)
@@ -26,6 +27,7 @@ SET(kvidcc_SRCS
send.cpp
thread.cpp
utils.cpp
+ video.cpp
voice.cpp
window.cpp
)
diff --git a/src/modules/dcc/broker.cpp b/src/modules/dcc/broker.cpp
index 4d0453aa8..d0c64b145 100644
--- a/src/modules/dcc/broker.cpp
+++ b/src/modules/dcc/broker.cpp
@@ -27,6 +27,7 @@
#include "chat.h"
#include "send.h"
#include "voice.h"
+#include "video.h"
#ifdef COMPILE_DCC_CANVAS
#include "canvas.h"
@@ -398,6 +399,75 @@ void KviDccBroker::passiveVoiceExecute(KviDccDescriptor * dcc)
///////////////////////////////////////////////////////////////////////////////
+// ACTIVE VIDEO
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::activeVideoManage(KviDccDescriptor * dcc)
+{
+ if(!dcc->bAutoAccept)
+ {
+ // need confirmation
+ QString tmp = __tr2qs_ctx(
+ "<b>%1 [%2@%3]</b> requests a<br>" \
+ "<b>Direct Client Connection</b> in <b>VIDEO</b> mode.<br>" \
+ "The connection target will be host <b>%4</b> on port <b>%5</b><br>" \
+ ,"dcc" \
+ ).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szIp).arg(dcc->szPort);
+
+ KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,__tr2qs_ctx("DCC VIDEO request","dcc"));
+ m_pBoxList->append(box);
+ connect(box,SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(activeVideoExecute(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
+ box->show();
+ } else {
+ // auto accept
+ activeVideoExecute(0,dcc);
+ }
+}
+
+void KviDccBroker::activeVideoExecute(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // rebind to the first available console....
+ dcc->setConsole(g_pApp->activeConsole());
+ }
+
+ KviStr tmp(KviStr::Format,"dcc: video %s@%s:%s",dcc->szNick.toUtf8().data(),dcc->szIp.toUtf8().data(),dcc->szPort.toUtf8().data());
+ KviDccVideo * v = new KviDccVideo(dcc->console()->frame(),dcc,tmp.ptr());
+
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
+ (KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVideo) || \
+ (dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVideoWhenAutoAccepted)));
+
+ dcc->console()->frame()->addWindow(v,!bMinimized);
+ if(bMinimized)v->minimize();
+
+ m_pDccWindowList->append(v);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// PASSIVE VOICE
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::passiveVideoExecute(KviDccDescriptor * dcc)
+{
+ KviStr tmp(KviStr::Format,"dcc: video %s@%s:%s",dcc->szNick.toUtf8().data(),dcc->szIp.toUtf8().data(),dcc->szPort.toUtf8().data());
+ KviDccVideo * v = new KviDccVideo(dcc->console()->frame(),dcc,tmp.ptr());
+ //#warning "Create minimized dcc video ?... or maybe it's too much ? :)"
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat);
+ dcc->console()->frame()->addWindow(v,!bMinimized);
+ if(bMinimized)v->minimize();
+ m_pDccWindowList->append(v);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
// ACTIVE CANVAS
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/modules/dcc/broker.h b/src/modules/dcc/broker.h
index 5be531571..338ebb853 100644
--- a/src/modules/dcc/broker.h
+++ b/src/modules/dcc/broker.h
@@ -86,6 +86,9 @@ public:
void activeVoiceManage(KviDccDescriptor * dcc);
void passiveVoiceExecute(KviDccDescriptor * dcc);
+ void activeVideoManage(KviDccDescriptor * dcc);
+ void passiveVideoExecute(KviDccDescriptor * dcc);
+
void recvFileManage(KviDccDescriptor * dcc);
void sendFileManage(KviDccDescriptor * dcc);
@@ -101,6 +104,7 @@ public slots:
void activeCanvasExecute(KviDccBox * box,KviDccDescriptor * dcc);
void activeVoiceExecute(KviDccBox * box,KviDccDescriptor * dcc);
+ void activeVideoExecute(KviDccBox * box,KviDccDescriptor * dcc);
void sendFileExecute(KviDccBox * box,KviDccDescriptor * dcc);
void recvFileExecute(KviDccBox * box,KviDccDescriptor * dcc);
diff --git a/src/modules/dcc/codec.cpp b/src/modules/dcc/codec.cpp
index d08a1c87f..1ea1172c9 100644
--- a/src/modules/dcc/codec.cpp
+++ b/src/modules/dcc/codec.cpp
@@ -88,3 +88,70 @@ int KviDccVoiceNullCodec::decodedFrameSize()
{
return 1024;
}
+
+//--------------------------
+
+KviDccVideoCodec::KviDccVideoCodec()
+{
+}
+
+KviDccVideoCodec::~KviDccVideoCodec()
+{
+}
+
+void KviDccVideoCodec::encode(KviDataBuffer *,KviDataBuffer *)
+{
+}
+
+void KviDccVideoCodec::decode(KviDataBuffer *,KviDataBuffer *)
+{
+}
+
+int KviDccVideoCodec::encodedFrameSize()
+{
+ return 0;
+}
+
+int KviDccVideoCodec::decodedFrameSize()
+{
+ return 0;
+}
+
+const char * KviDccVideoCodec::name()
+{
+ return m_szName.ptr();
+}
+
+KviDccVideoNullCodec::KviDccVideoNullCodec()
+: KviDccVideoCodec()
+{
+ m_szName = "null (no compression)";
+}
+
+KviDccVideoNullCodec::~KviDccVideoNullCodec()
+{
+}
+
+void KviDccVideoNullCodec::encode(KviDataBuffer * signal,KviDataBuffer * stream)
+{
+ if(signal->size() < 1)return;
+ stream->append(signal->data(),signal->size());
+ signal->resize(0);
+}
+
+void KviDccVideoNullCodec::decode(KviDataBuffer * stream,KviDataBuffer * signal)
+{
+ if(stream->size() < 1)return;
+ signal->append(stream->data(),stream->size());
+ stream->resize(0);
+}
+
+int KviDccVideoNullCodec::encodedFrameSize()
+{
+ return 1024;
+}
+
+int KviDccVideoNullCodec::decodedFrameSize()
+{
+ return 1024;
+}
diff --git a/src/modules/dcc/codec.h b/src/modules/dcc/codec.h
index 5cd8ee85b..7f0ed4f58 100644
--- a/src/modules/dcc/codec.h
+++ b/src/modules/dcc/codec.h
@@ -54,4 +54,30 @@ public:
virtual int decodedFrameSize();
};
+class KviDccVideoCodec
+{
+public:
+ KviDccVideoCodec();
+ virtual ~KviDccVideoCodec();
+protected:
+ KviStr m_szName;
+public:
+ const char * name();
+ virtual void encode(KviDataBuffer * signal,KviDataBuffer * stream);
+ virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal);
+ virtual int encodedFrameSize();
+ virtual int decodedFrameSize();
+};
+
+class KviDccVideoNullCodec : public KviDccVideoCodec
+{
+public:
+ KviDccVideoNullCodec();
+ virtual ~KviDccVideoNullCodec();
+public:
+ virtual void encode(KviDataBuffer * signal,KviDataBuffer * stream);
+ virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal);
+ virtual int encodedFrameSize();
+ virtual int decodedFrameSize();
+};
#endif //_CODEC_H_
diff --git a/src/modules/dcc/libkvidcc.cpp b/src/modules/dcc/libkvidcc.cpp
index 620a6f3e6..3231a68df 100644
--- a/src/modules/dcc/libkvidcc.cpp
+++ b/src/modules/dcc/libkvidcc.cpp
@@ -25,6 +25,7 @@
#include "gsmcodec.h"
#include "broker.h"
#include "voice.h"
+#include "video.h"
#include "utils.h"
#include "send.h"
#include "window.h"
@@ -1181,6 +1182,69 @@ static bool dcc_kvs_cmd_voice(KviKvsModuleCommandCall * c)
}
+static bool dcc_kvs_cmd_video(KviKvsModuleCommandCall * c)
+{
+ QString szTarget;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETERS_END(c)
+
+#ifdef COMPILE_DISABLE_DCC_VIDEO
+ c->warning(__tr2qs_ctx("DCC VIDEO support not enabled at compilation time","dcc"));
+ return true;
+#endif
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+
+ d->szNick = szTarget; // we always specify the nickname
+ d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
+ d->szHost = d->szUser; // host is always unknown
+
+ if(!dcc_kvs_parse_default_parameters(d,c))return false;
+
+ d->szCodec = "null";
+
+ if(KviKvsVariant * pCodec = c->switches()->find('g',"codec"))
+ {
+ QString szCodec;
+ pCodec->asString(szCodec);
+
+ if(!kvi_dcc_video_is_valid_codec(szCodec.toUtf8().data()))
+ {
+ c->warning(__tr2qs_ctx("Invalid codec specified, defaulting to 'null'","dcc"));
+ d->szCodec = "null";
+ }
+ }
+
+ dcc_module_set_dcc_type(d,"VIDEO");
+ if(c->switches()->find('c',"connect"))
+ {
+ if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
+ return false;
+ }
+ d->szIp = d->szListenIp;
+ d->szPort = d->szListenPort;
+ d->szListenIp = ""; // useless
+ d->szListenPort = ""; // useless
+ d->bActive = true;
+
+ d->triggerCreationEvent();
+ g_pDccBroker->activeVideoExecute(0,d);
+ } else {
+ d->szIp = __tr2qs_ctx("unknown","dcc");
+ d->szPort = d->szIp;
+ d->bActive = false;
+ d->bSendRequest = !(c->switches()->find('n',"no-ctcp"));
+
+ d->triggerCreationEvent();
+ g_pDccBroker->passiveVideoExecute(d);
+ }
+
+ return true;
+}
/*
@@ -2698,6 +2762,7 @@ static bool dcc_module_init(KviModule * m)
KVSM_REGISTER_SIMPLE_COMMAND(m,"send",dcc_kvs_cmd_send);
KVSM_REGISTER_SIMPLE_COMMAND(m,"chat",dcc_kvs_cmd_chat);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"video",dcc_kvs_cmd_video);
KVSM_REGISTER_SIMPLE_COMMAND(m,"voice",dcc_kvs_cmd_voice);
KVSM_REGISTER_SIMPLE_COMMAND(m,"recv",dcc_kvs_cmd_recv);
KVSM_REGISTER_SIMPLE_COMMAND(m,"rsend",dcc_kvs_cmd_rsend);
diff --git a/src/modules/dcc/requests.cpp b/src/modules/dcc/requests.cpp
index 5078dea91..3b27014c5 100644
--- a/src/modules/dcc/requests.cpp
+++ b/src/modules/dcc/requests.cpp
@@ -26,6 +26,7 @@
#include "gsmcodec.h"
#include "broker.h"
+#include "video.h"
#include "voice.h"
#include "utils.h"
#include "send.h"
@@ -1041,6 +1042,79 @@ static void dccModuleParseDccVoice(KviDccRequest *dcc)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// VIDEO
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccVideo(KviDccRequest *dcc)
+{
+ //
+ // We have received a DCC VIDEO request in the following form:
+ //
+ // DCC VIDEO codec <ipaddress> <port>
+ //
+ // This means that we're requested to setup an ACTIVE voice connection
+ // ... Easy task :)
+ //
+
+ if(!dcc_module_check_limits(dcc))return;
+
+ if(!dcc_module_normalize_target_data(dcc,dcc->szParam2,dcc->szParam3))return;
+
+#ifdef COMPILE_DISABLE_DCC_VIDEO
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCERROR,
+ __tr2qs_ctx("The above request cannot be accepted: DCC VIDEO support not enabled at compilation time ","dcc"));
+ return;
+ }
+#endif
+ // Actually unused parameter
+ if(!kvi_dcc_video_is_valid_codec(dcc->szParam1.ptr()))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCERROR,
+ __tr2qs_ctx("The above request cannot be accepted: Unsupported codec '%s'","dcc"),dcc->szParam1.ptr());
+ return;
+ }
+ }
+
+// bool bOk;
+
+// int iSampleRate = dcc->szParam4.toInt(&bOk);
+// if(!bOk)
+// {
+// if(!dcc->ctcpMsg->msg->haltOutput())
+// {
+// dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+// __tr2qs_ctx("The above request appears to be broken: Invalid sample-rate '%s', defaulting to 8000","dcc"),dcc->szParam4.ptr());
+// }
+// iSampleRate = 8000;
+// }
+
+
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->user();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+ dcc_fill_local_nick_user_host(d,dcc);
+
+
+ d->szIp = dcc->szParam2.ptr();
+ d->szPort = dcc->szParam3.ptr();
+ d->bActive = true; // we have to connect
+ d->bIsTdcc = false;
+ d->bNoAcks = false; // this has no meaning in voice
+ d->szCodec = dcc->szParam1;
+// d->iSampleRate = iSampleRate;
+ d->bOverrideMinimize = false;
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccVideo);
+ dcc_module_set_dcc_type(d,"VIDEO");
+ d->triggerCreationEvent();
+ g_pDccBroker->activeVideoManage(d);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CANVAS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1101,7 +1175,7 @@ typedef struct _dccParseProcEntry
dccParseProc proc;
} dccParseProcEntry;
-#define KVI_NUM_KNOWN_DCC_TYPES 27
+#define KVI_NUM_KNOWN_DCC_TYPES 28
static dccParseProcEntry dccParseProcTable[KVI_NUM_KNOWN_DCC_TYPES]=
{
@@ -1131,7 +1205,8 @@ static dccParseProcEntry dccParseProcTable[KVI_NUM_KNOWN_DCC_TYPES]=
{ "STRSEND", dccModuleParseDccRSend },
{ "TSRSEND", dccModuleParseDccRSend },
{ "CANVAS" , dccModuleParseDccCanvas },
- { "VOICE" , dccModuleParseDccVoice }
+ { "VOICE" , dccModuleParseDccVoice },
+ { "VIDEO" , dccModuleParseDccVideo }
};
diff --git a/src/modules/dcc/video.cpp b/src/modules/dcc/video.cpp
new file mode 100644
index 000000000..525b356c7
--- /dev/null
+++ b/src/modules/dcc/video.cpp
@@ -0,0 +1,686 @@
+//=============================================================================
+//
+// File : video.cpp
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "video.h"
+#include "marshal.h"
+#include "broker.h"
+
+#include "kvi_settings.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_error.h"
+#include "kvi_netutils.h"
+#include "kvi_options.h"
+#include "kvi_console.h"
+#include "kvi_malloc.h"
+#include "kvi_socket.h"
+#include "kvi_ircconnection.h"
+#include "kvi_tal_vbox.h"
+
+#include <QToolTip>
+#include <QByteArray>
+#include <QBuffer>
+
+extern KviDccBroker * g_pDccBroker;
+
+//Check for the *SS Api....we don't want to fail here...
+
+bool kvi_dcc_video_is_valid_codec(const char * codecName)
+{
+// if(kvi_strEqualCI("jpeg",codecName))return true;
+ if(kvi_strEqualCI("null",codecName))return true;
+ return false;
+}
+
+static KviDccVideoCodec * kvi_dcc_video_get_codec(const char *)
+{
+// if(kvi_strEqualCI("jpeg",codecName))return new KviDccVoiceAdpcmCodec();
+ //if(kvi_strEqualCI("null",codecName))
+ return new KviDccVideoNullCodec();
+// return new KviDccVoiceAdpcmCodec();
+}
+
+
+KviDccVideoThread::KviDccVideoThread(KviWindow * wnd,kvi_socket_t fd,KviDccVideoThreadOptions * opt)
+: KviDccThread(wnd,fd)
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ m_pOpt = opt;
+ m_bPlaying = false;
+ m_bRecording = false;
+ m_pInfoMutex = new KviMutex();
+ m_bRecordingRequestPending = false;
+#endif
+ startRecording();
+ startPlaying();
+}
+
+KviDccVideoThread::~KviDccVideoThread()
+{
+ stopRecording();
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ delete m_pOpt->pCodec;
+ delete m_pOpt;
+ delete m_pInfoMutex;
+#endif
+}
+
+bool KviDccVideoThread::readWriteStep()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ // Socket management
+ bool bCanRead;
+ bool bCanWrite;
+
+ if(kvi_select(m_fd,&bCanRead,&bCanWrite))
+ {
+ if(bCanRead)
+ {
+ unsigned int actualSize = m_inFrameBuffer.size();
+ m_inFrameBuffer.resize(actualSize + 1024);
+ int readLen = kvi_socket_recv(m_fd,(void *)(m_inFrameBuffer.data() + actualSize),1024);
+ if(readLen > 0)
+ {
+ if(readLen < 1024)m_inFrameBuffer.resize(actualSize + readLen);
+ m_pOpt->pCodec->decode(&m_inFrameBuffer,&m_inSignalBuffer);
+//#warning "A maximum length for the signal buffer is actually needed!!!"
+ } else {
+ if(!handleInvalidSocketRead(readLen))return false;
+ m_inFrameBuffer.resize(actualSize);
+ }
+ }// else {
+ // m_uSleepTime += 100;
+ //}
+
+ if(bCanWrite)
+ {
+ // Have somethihg to write ?
+ if(m_outFrameBuffer.size() > 0)
+ {
+ int written = kvi_socket_send(m_fd,m_outFrameBuffer.data(),m_outFrameBuffer.size());
+ if(written > 0)
+ {
+ m_outFrameBuffer.remove(written);
+ } else {
+ if(!handleInvalidSocketRead(written))return false;
+ }
+ }// else {
+ // m_uSleepTime += 100;
+ // }
+ }// else {
+ // m_uSleepTime += 100;
+// }
+//#warning "Usleep here ?"
+ }// else {
+// if(!(m_bPlaying || m_bRecording))
+// {
+// // Really NOTHING is happening...sleep a bit more
+// m_uSleepTime += 800;
+// } else {
+// m_uSleepTime += 100;
+// }
+// }
+
+#endif // !COMPILE_DISABLE_DCC_VOICE
+ return true;
+}
+
+bool KviDccVideoThread::videoStep()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ // Are we playing ?
+ if(m_bPlaying)
+ {
+ if(m_inSignalBuffer.size() > 0)
+ {
+ unsigned const char jpg_magic_init[4] = { 0xFF, 0xD8, 0xFF, 0xE0}; //SOI + APP0
+ unsigned const char jpg_magic_end[2] = { 0xFF, 0xD9}; //EOI
+ int start = m_inSignalBuffer.find(jpg_magic_init, 4);
+ int end = m_inSignalBuffer.find(jpg_magic_end, 2);
+ qDebug("start %d end %d", start, end);
+ if(start != -1 && end != -1)
+ {
+ //remove junk before jpeg start
+ m_inSignalBuffer.remove(start);
+ int len = end - start + 1;
+ QImage img;
+ img.loadFromData(m_inSignalBuffer.data(), len, "JPEG");
+ if(!img.isNull())
+ {
+ m_inImage = img;
+ qDebug("img in");
+ }
+ m_inSignalBuffer.remove(len);
+ }
+ }
+ }
+
+ // Are we recording ?
+ if(m_bRecording)
+ {
+ //grab the image, compress using the codec
+ QByteArray ba;
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::WriteOnly);
+ //0 to obtain small compressed files,
+ //100 for large uncompressed files,
+ //and -1 (the default) to use the default settings.
+ ((KviDccVideo*)KviDccThread::parent())->m_Image.save(&buffer, "JPEG", 20);
+ if(ba.size() > 0)
+ {
+ m_outSignalBuffer.append((const unsigned char*) ba.data(), ba.size());
+ m_pOpt->pCodec->encode(&m_outSignalBuffer,&m_outFrameBuffer);
+ }
+ }
+
+#endif // !COMPILE_DISABLE_DCC_VIDEO
+ return true;
+}
+
+void KviDccVideoThread::startRecording()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ //debug("Start recording");
+ if(m_bRecording)return; // already started
+
+ //if(openSoundcardForReading())
+ if(1)
+ {
+// debug("Posting event");
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VIDEO_THREAD_ACTION_START_RECORDING));
+ postEvent(KviDccThread::parent(),e);
+
+ m_bRecording = true;
+ m_bRecordingRequestPending = false;
+ } else {
+ m_bRecordingRequestPending = true;
+ }
+#endif
+}
+
+void KviDccVideoThread::stopRecording()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ //debug("Stop recording");
+ m_bRecordingRequestPending = false;
+ if(!m_bRecording)return; // already stopped
+
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VIDEO_THREAD_ACTION_STOP_RECORDING));
+ postEvent(KviDccThread::parent(),e);
+
+ m_bRecording = false;
+// if(!m_bPlaying)closeSoundcard();
+#endif
+}
+
+void KviDccVideoThread::startPlaying()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ //debug("Start playing");
+ if(m_bPlaying)return;
+
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VIDEO_THREAD_ACTION_START_PLAYING));
+ postEvent(KviDccThread::parent(),e);
+ m_bPlaying = true;
+
+#endif
+}
+
+void KviDccVideoThread::stopPlaying()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ //debug("Stop playing");
+ if(!m_bPlaying)return;
+
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VIDEO_THREAD_ACTION_STOP_PLAYING));
+ postEvent(KviDccThread::parent(),e);
+
+ m_bPlaying = false;
+#endif
+}
+
+void KviDccVideoThread::run()
+{
+#ifndef COMPILE_DISABLE_DCC_VIDEO
+ for(;;)
+ {
+// m_uSleepTime = 0;
+
+ // Dequeue events
+ while(KviThreadEvent * e = dequeueEvent())
+ {
+ if(e->id() == KVI_THREAD_EVENT_TERMINATE)
+ {
+ delete e;
+ goto exit_dcc;
+ } else if(e->id() == KVI_DCC_THREAD_EVENT_ACTION)
+ {
+ int * act = ((KviThreadDataEvent<int> *)e)->getData();
+ if(*act)startRecording();
+ else stopRecording();
+ delete act;
+ delete e;
+ } else {
+ // Other events are senseless to us
+ delete e;
+ }
+ }
+
+ if(!readWriteStep())goto exit_dcc;
+ if(!videoStep())goto exit_dcc;
+
+ m_pInfoMutex->lock();
+ m_iInputBufferSize = m_inSignalBuffer.size();
+ m_iOutputBufferSize = (m_outFrameBuffer.size() / m_pOpt->pCodec->encodedFrameSize()) * m_pOpt->pCodec->decodedFrameSize();
+ m_pInfoMutex->unlock();
+
+ // Start recording if the request was not fulfilled yet
+ if(m_bRecordingRequestPending)startRecording();
+ }
+
+
+exit_dcc:
+
+#endif //! COMPILE_DISABLE_DCC_VIDEO
+ kvi_socket_close(m_fd);
+ m_fd = KVI_INVALID_SOCKET;
+}
+
+KviDccVideo::KviDccVideo(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name)
+: KviDccWindow(KVI_WINDOW_TYPE_DCCVOICE,pFrm,name,dcc)
+{
+ m_pDescriptor = dcc;
+ m_pSlaveThread = 0;
+ m_pszTarget = 0;
+
+ m_pLayout = new QGridLayout();
+
+ //remote video
+ m_pInVideoLabel = new QLabel();
+ m_pInVideoLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_pInVideoLabel->setMinimumSize(320, 240);
+ m_pInVideoLabel->setFrameShape(QFrame::Box);
+ m_pInVideoLabel->setScaledContents(true);
+ m_pInVideoLabel->setAlignment(Qt::AlignCenter);
+ m_pLayout->addWidget(m_pInVideoLabel, 0, 0, 10, 1);
+
+ //local video
+ m_pOutVideoLabel = new QLabel();
+ m_pOutVideoLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_pOutVideoLabel->setMinimumSize(320, 240);
+ m_pOutVideoLabel->setFrameShape(QFrame::Box);
+ m_pOutVideoLabel->setScaledContents(true);
+ m_pOutVideoLabel->setAlignment(Qt::AlignCenter);
+ m_pLayout->addWidget(m_pOutVideoLabel, 11, 0, 10, 1);
+
+ //local video input
+ m_pVideoDevicePool = Kopete::AV::VideoDevicePool::self();
+ m_pVideoDevicePool->open();
+ m_pVideoDevicePool->setSize(320, 240);
+
+ //local video input: config
+ m_pLabel[0] = new QLabel();
+ m_pLabel[0]->setText(__tr2qs_ctx("Video device:","dcc"));
+ m_pLayout->addWidget(m_pLabel[0], 11, 1, 1, 1);
+
+ m_pCDevices = new QComboBox();
+ m_pVideoDevicePool->fillDeviceQComboBox(m_pCDevices);
+ m_pLayout->addWidget(m_pCDevices, 12, 1, 1, 1);
+
+ m_pLabel[1] = new QLabel();
+ m_pLabel[1]->setText(__tr2qs_ctx("Input:","dcc"));
+ m_pLayout->addWidget(m_pLabel[1], 13, 1, 1, 1);
+
+ m_pCInputs = new QComboBox();
+ m_pVideoDevicePool->fillInputQComboBox(m_pCInputs);
+ m_pLayout->addWidget(m_pCInputs, 14, 1, 1, 1);
+
+ m_pLabel[2] = new QLabel();
+ m_pLabel[2]->setText(__tr2qs_ctx("Standard:","dcc"));
+ m_pLayout->addWidget(m_pLabel[2], 15, 1, 1, 1);
+
+ m_pCStandards = new QComboBox();
+ m_pVideoDevicePool->fillStandardQComboBox(m_pCStandards);
+ m_pLayout->addWidget(m_pCStandards, 16, 1, 1, 1);
+
+ setLayout(m_pLayout);
+
+ m_pVideoDevicePool->startCapturing();
+
+ connect(m_pVideoDevicePool, SIGNAL(deviceRegistered(const QString &) ), SLOT(deviceRegistered(const QString &)) );
+ connect(m_pVideoDevicePool, SIGNAL(deviceUnregistered(const QString &) ), SLOT(deviceUnregistered(const QString &)) );
+
+ connect(&m_Timer, SIGNAL(timeout()), this, SLOT(slotUpdateImage()) );
+ if ( m_pVideoDevicePool->hasDevices() )
+ {
+ m_Timer.start(40); //25fps
+ }
+
+ m_pMarshal = new KviDccMarshal(this);
+ connect(m_pMarshal,SIGNAL(error(int)),this,SLOT(handleMarshalError(int)));
+ connect(m_pMarshal,SIGNAL(connected()),this,SLOT(connected()));
+ connect(m_pMarshal,SIGNAL(inProgress()),this,SLOT(connectionInProgress()));
+
+ startConnection();
+}
+
+KviDccVideo::~KviDccVideo()
+{
+ m_pVideoDevicePool->close();
+
+ if(m_pInVideoLabel)
+ {
+ delete m_pInVideoLabel;
+ m_pInVideoLabel=0;
+ }
+ if(m_pOutVideoLabel)
+ {
+ delete m_pOutVideoLabel;
+ m_pOutVideoLabel=0;
+ }
+ if(m_pCDevices)
+ {
+ delete m_pCDevices;
+ m_pCDevices=0;
+ }
+ if(m_pCInputs)
+ {
+ delete m_pCInputs;
+ m_pCInputs=0;
+ }
+ if(m_pCStandards)
+ {
+ delete m_pCStandards;
+ m_pCStandards=0;
+ }
+ if(m_pLabel[0])
+ {
+ delete m_pLabel[2];
+ delete m_pLabel[1];
+ delete m_pLabel[0];
+ m_pLabel[2] = 0;
+ m_pLabel[1] = 0;
+ m_pLabel[0] = 0;
+ }
+ if(m_pLayout)
+ {
+ delete m_pLayout;
+ m_pLayout=0;
+ }
+
+ g_pDccBroker->unregisterDccWindow(this);
+
+ if(m_pSlaveThread)
+ {
+ m_pSlaveThread->terminate();
+ delete m_pSlaveThread;
+ m_pSlaveThread = 0;
+ }
+
+ KviThreadManager::killPendingEvents(this);
+
+ if(m_pszTarget)
+ {
+ delete m_pszTarget;
+ m_pszTarget = 0;
+ }
+}
+
+void KviDccVideo::startConnection()
+{
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting a passive DCC VIDEO connection","dcc"));
+ int ret = m_pMarshal->dccListen(m_pDescriptor->szListenIp,m_pDescriptor->szListenPort,m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ } else {
+ // ACTIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting an active DCC VIDEO connection","dcc"));
+ int ret = m_pMarshal->dccConnect(m_pDescriptor->szIp.toUtf8().data(),m_pDescriptor->szPort.toUtf8().data(),m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ }
+}
+
+void KviDccVideo::connectionInProgress()
+{
+ if(m_pDescriptor->bActive)
+ {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Contacting host %Q on port %Q","dcc"),&(m_pDescriptor->szIp),&(m_pDescriptor->szPort));
+ } else {
+
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Listening on interface %Q port %Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+
+ if(m_pDescriptor->bSendRequest)
+ {
+ QString ip = !m_pDescriptor->szFakeIp.isEmpty() ? m_pDescriptor->szFakeIp : m_pDescriptor->szListenIp;
+ KviStr port = !m_pDescriptor->szFakePort.isEmpty() ? m_pDescriptor->szFakePort : m_pMarshal->localPort();
+//#warning "OPTION FOR SENDING 127.0.0.1 and so on (not an unsigned nuumber)"
+ struct in_addr a;
+ if(KviNetUtils::stringIpToBinaryIp(ip,&a)) {
+ ip.setNum(htonl(a.s_addr));
+ }
+
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC VIDEO %s %Q %s %d%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,m_pDescriptor->szCodec.ptr(),
+ &ip,port.ptr(),m_pDescriptor->iSampleRate,0x01);
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Sent DCC VIDEO (%s) request to %Q, waiting for the remote client to connect...","dcc"),
+ m_pDescriptor->szCodec.ptr(),&(m_pDescriptor->szNick));
+ } else output(KVI_OUT_DCCMSG,__tr2qs_ctx("DCC VIDEO request not sent: awaiting manual connections","dcc"));
+ }
+}
+
+const QString & KviDccVideo::target()
+{
+ // This may change on the fly...
+ if(!m_pszTarget)
+ m_pszTarget = new QString();
+
+ m_pszTarget->sprintf("%s@%s:%s",m_pDescriptor->szNick.toUtf8().data(),m_pDescriptor->szIp.toUtf8().data(),m_pDescriptor->szPort.toUtf8().data());
+ return *m_pszTarget;
+}
+
+void KviDccVideo::getBaseLogFileName(QString &buffer)
+{
+ buffer.sprintf("dccvideo_%s_%s_%s",m_pDescriptor->szNick.toUtf8().data(),m_pDescriptor->szLocalFileName.toUtf8().data(),m_pDescriptor->szPort.toUtf8().data());
+}
+
+void KviDccVideo::fillCaptionBuffers()
+{
+ KviStr tmp(KviStr::Format,"DCC Video %s@%s:%s %s",
+ m_pDescriptor->szNick.toUtf8().data(),m_pDescriptor->szIp.toUtf8().data(),m_pDescriptor->szPort.toUtf8().data(),
+ m_pDescriptor->szLocalFileName.toUtf8().data());
+
+ m_szPlainTextCaption = tmp;
+}
+
+QPixmap * KviDccVideo::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCVOICE);
+}
+
+bool KviDccVideo::event(QEvent *e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ switch(((KviThreadEvent *)e)->id())
+ {
+ case KVI_DCC_THREAD_EVENT_ERROR:
+ {
+ int * err = ((KviThreadDataEvent<int> *)e)->getData();
+ QString ssss = KviError::getDescription(*err);
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("ERROR: %Q","dcc"),&(ssss));
+ delete err;
+/* m_pTalkButton->setEnabled(false);
+ m_pRecordingLabel->setEnabled(false);
+ m_pPlayingLabel->setEnabled(false);*/
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_MESSAGE:
+ {
+ KviStr * str = ((KviThreadDataEvent<KviStr> *)e)->getData();
+ outputNoFmt(KVI_OUT_DCCMSG,__tr_no_xgettext_ctx(str->ptr(),"dcc"));
+ delete str;
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_ACTION:
+ {
+ int * act = ((KviThreadDataEvent<int> *)e)->getData();
+ switch(*act)
+ {
+ case KVI_DCC_VIDEO_THREAD_ACTION_START_RECORDING:
+// m_pRecordingLabel->setEnabled(true);
+ break;
+ case KVI_DCC_VIDEO_THREAD_ACTION_STOP_RECORDING:
+// m_pRecordingLabel->setEnabled(false);
+ break;
+ case KVI_DCC_VIDEO_THREAD_ACTION_START_PLAYING:
+// m_pPlayingLabel->setEnabled(true);
+ break;
+ case KVI_DCC_VIDEO_THREAD_ACTION_STOP_PLAYING:
+// m_pPlayingLabel->setEnabled(false);
+ break;
+ }
+ delete act;
+ return true;
+ }
+ break;
+ default:
+ debug("Invalid event type %d received",((KviThreadEvent *)e)->id());
+ break;
+ }
+
+ }
+
+ return KviWindow::event(e);
+}
+
+void KviDccVideo::handleMarshalError(int err)
+{
+ QString ssss = KviError::getDescription(err);
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("DCC Failed: %Q","dcc"),&ssss);
+/* m_pTalkButton->setEnabled(false);
+ m_pTalkButton->setChecked(false);
+ m_pRecordingLabel->setEnabled(false);
+ m_pPlayingLabel->setEnabled(false);*/
+}
+
+void KviDccVideo::connected()
+{
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Connected to %Q:%Q","dcc"),
+ &(m_pMarshal->remoteIp()),&(m_pMarshal->remotePort()));
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Local end is %Q:%Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+ if(!(m_pDescriptor->bActive))
+ {
+ m_pDescriptor->szIp = m_pMarshal->remoteIp();
+ m_pDescriptor->szPort = m_pMarshal->remotePort();
+ m_pDescriptor->szHost = m_pMarshal->remoteIp();
+ }
+ updateCaption();
+
+ KviDccVideoThreadOptions * opt = new KviDccVideoThreadOptions;
+
+ opt->pCodec = kvi_dcc_video_get_codec(m_pDescriptor->szCodec.ptr());
+
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Actual codec used is '%s'","dcc"),opt->pCodec->name());
+
+ m_pSlaveThread = new KviDccVideoThread(this,m_pMarshal->releaseSocket(),opt);
+ m_pSlaveThread->start();
+
+// m_pTalkButton->setEnabled(true);
+}
+
+void KviDccVideo::stopTalking()
+{
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(0));
+ m_pSlaveThread->enqueueEvent(e);
+}
+
+void KviDccVideo::startTalking()
+{
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(1));
+ m_pSlaveThread->enqueueEvent(e);
+}
+
+void KviDccVideo::startOrStopTalking(bool bStart)
+{
+ if(bStart)startTalking();
+ else stopTalking();
+}
+
+void KviDccVideo::slotUpdateImage()
+{
+ m_pVideoDevicePool->getFrame();
+ m_pVideoDevicePool->getImage(&m_Image);
+ if(isVisible())
+ {
+ m_pOutVideoLabel->setPixmap(QPixmap::fromImage(m_Image.mirrored(m_pVideoDevicePool->getImageAsMirror(),false)));
+ if(m_pSlaveThread)
+ m_pInVideoLabel->setPixmap(QPixmap::fromImage(m_pSlaveThread->m_inImage));
+ }
+}
+
+void KviDccVideo::deviceRegistered(const QString &)
+{
+ m_pVideoDevicePool->fillDeviceQComboBox(m_pCDevices);
+ m_pVideoDevicePool->fillInputQComboBox(m_pCInputs);
+ m_pVideoDevicePool->fillStandardQComboBox(m_pCStandards);
+
+ // update the mVideoImageLabel to show the camera frames
+ m_pVideoDevicePool->open();
+ m_pVideoDevicePool->setSize(320, 240);
+ m_pVideoDevicePool->startCapturing();
+
+// setVideoInputParameters();
+
+ if ( m_pVideoDevicePool->hasDevices() )
+ {
+ m_Timer.start(200); //5fps
+ }
+}
+
+
+void KviDccVideo::deviceUnregistered(const QString & )
+{
+ m_pVideoDevicePool->fillDeviceQComboBox(m_pCDevices);
+ m_pVideoDevicePool->fillInputQComboBox(m_pCInputs);
+ m_pVideoDevicePool->fillStandardQComboBox(m_pCStandards);
+}
+
+#ifndef COMPILE_USE_STANDALONE_MOC_SOURCES
+#include "m_video.moc"
+#endif //!COMPILE_USE_STANDALONE_MOC_SOURCES
diff --git a/src/modules/dcc/video.h b/src/modules/dcc/video.h
new file mode 100644
index 000000000..abae4db38
--- /dev/null
+++ b/src/modules/dcc/video.h
@@ -0,0 +1,155 @@
+#ifndef _VIDEO_H_
+#define _VIDEO_H_
+//=============================================================================
+//
+// File : video.h
+// Creation date : Tue Nov 10 18:08:09 2009 GMT by Fabio Bas
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2009 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "codec.h"
+#include "descriptor.h"
+#include "thread.h"
+#include "window.h"
+
+#include "kvi_window.h"
+#include "kvi_databuffer.h"
+#include "kvi_sockettype.h"
+#include "kvi_tal_hbox.h"
+
+#include <QLabel>
+#include <QToolButton>
+#include <QTimer>
+#include <QImage>
+#include <QPixmap>
+#include <QComboBox>
+#include <QGridLayout>
+
+#include "avdevice/videodevicepool.h"
+
+class QSlider;
+class KviDccMarshal;
+
+#ifndef _DCC_VIDEO_CPP_
+ extern bool kvi_dcc_video_is_valid_codec(const char * codecName);
+#endif
+
+#define KVI_DCC_VIDEO_THREAD_ACTION_START_RECORDING 0
+#define KVI_DCC_VIDEO_THREAD_ACTION_STOP_RECORDING 1
+#define KVI_DCC_VIDEO_THREAD_ACTION_START_PLAYING 2
+#define KVI_DCC_VIDEO_THREAD_ACTION_STOP_PLAYING 3
+
+typedef struct _KviDccVideoThreadOptions
+{
+ QString szVideoDevice;
+ KviDccVideoCodec * pCodec;
+} KviDccVideoThreadOptions;
+
+class KviDccVideoThread : public KviDccThread
+{
+ friend class KviDccVideo;
+public:
+ KviDccVideoThread(KviWindow * wnd,kvi_socket_t fd,KviDccVideoThreadOptions * opt);
+ ~KviDccVideoThread();
+protected:
+ KviDccVideoThreadOptions * m_pOpt;
+ KviDataBuffer m_outFrameBuffer;
+ KviDataBuffer m_inFrameBuffer;
+ KviDataBuffer m_inSignalBuffer;
+ KviDataBuffer m_outSignalBuffer;
+ bool m_bPlaying;
+ bool m_bRecording;
+ bool m_bRecordingRequestPending;
+ KviMutex * m_pInfoMutex;
+ // stuff protected by the mutex:
+ int m_iInputBufferSize;
+ int m_iOutputBufferSize;
+ QImage m_inImage;
+protected:
+ bool readWriteStep();
+ bool videoStep();
+ void startRecording();
+ void stopRecording();
+ void startPlaying();
+ void stopPlaying();
+ inline bool isPlaying() { return m_bPlaying; };
+ virtual void run();
+};
+
+
+class KviDccVideo : public KviDccWindow
+{
+ Q_OBJECT
+ friend class KviDccVideoThread;
+public:
+ KviDccVideo(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name);
+ ~KviDccVideo();
+protected:
+ QLabel *m_pInVideoLabel;
+ QLabel *m_pOutVideoLabel;
+ Kopete::AV::VideoDevicePool *m_pVideoDevicePool;
+ QComboBox *m_pCDevices;
+ QComboBox *m_pCInputs;
+ QComboBox *m_pCStandards;
+ QGridLayout *m_pLayout;
+ QImage m_Image;
+ QTimer m_Timer;
+ QLabel * m_pLabel[2];
+/*
+ KviTalHBox * m_pHBox;
+ QSlider * m_pVolumeSlider;
+ QLabel * m_pInputLabel;
+ QLabel * m_pOutputLabel;
+ QLabel * m_pRecordingLabel;
+ QLabel * m_pPlayingLabel;
+ QToolButton * m_pTalkButton;
+*/
+ QString * m_pszTarget;
+ KviDccVideoThread * m_pSlaveThread;
+protected:
+// virtual void focusInEvent(QFocusEvent *);
+ virtual const QString & target();
+ virtual void fillCaptionBuffers();
+ virtual QPixmap * myIconPtr();
+/*
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual QSize sizeHint() const;
+*/
+ virtual bool event(QEvent *e);
+ virtual void getBaseLogFileName(QString &buffer);
+ void startTalking();
+ void stopTalking();
+ void startConnection();
+// int getMixerVolume(void) const;
+protected slots:
+ void handleMarshalError(int err);
+ void connected();
+ void startOrStopTalking(bool bStart);
+/*
+ void setMixerVolume(int);
+*/
+ void connectionInProgress();
+ void slotUpdateImage();
+ void deviceRegistered(const QString &);
+ void deviceUnregistered(const QString &);
+};
+
+
+#endif //_VOICE_H_