aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/dcc
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/dcc')
-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
9 files changed, 1152 insertions, 2 deletions
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_