diff options
Diffstat (limited to 'src/modules/dcc')
| -rw-r--r-- | src/modules/dcc/codec.cpp | 92 | ||||
| -rw-r--r-- | src/modules/dcc/codec.h | 12 | ||||
| -rw-r--r-- | src/modules/dcc/libkvidcc.cpp | 2 | ||||
| -rw-r--r-- | src/modules/dcc/video.cpp | 758 | ||||
| -rw-r--r-- | src/modules/dcc/video.h | 47 |
5 files changed, 455 insertions, 456 deletions
diff --git a/src/modules/dcc/codec.cpp b/src/modules/dcc/codec.cpp index ffcbf330a..7e1433f1a 100644 --- a/src/modules/dcc/codec.cpp +++ b/src/modules/dcc/codec.cpp @@ -109,11 +109,11 @@ void KviDccVideoCodec::encodeVideo(KviDataBuffer *,KviDataBuffer *) { } -void KviDccVideoCodec::encodeAudio(KviDataBuffer *,KviDataBuffer *) +void KviDccVideoCodec::encodeText(KviDataBuffer *,KviDataBuffer *) { } -void KviDccVideoCodec::decode(KviDataBuffer *,KviDataBuffer *) +void KviDccVideoCodec::decode(KviDataBuffer *,KviDataBuffer *,KviDataBuffer *) { } @@ -162,40 +162,90 @@ void KviDccVideoSJpegCodec::encodeVideo(KviDataBuffer * videoSignal,KviDataBuffe videoSignal->clear(); } -void KviDccVideoSJpegCodec::encodeAudio(KviDataBuffer * audioSignal,KviDataBuffer * stream) +void KviDccVideoSJpegCodec::encodeText(KviDataBuffer * textSignal, KviDataBuffer * stream) { - //no audio support - Q_UNUSED(stream); - if(audioSignal->size() < 1) return; + static unsigned const char *irct_magic_init = (unsigned const char*) "\0<text>\0"; + static unsigned const char *irct_magic_end = (unsigned const char*) "\0</text>\0"; - audioSignal->clear(); + qDebug("encodeText %s %d",textSignal->data(), textSignal->size()); + if(textSignal->size() < 1) return; + stream->append(irct_magic_init,8); + stream->append((const unsigned char*)textSignal->data(),textSignal->size()); + stream->append(irct_magic_end,9); + textSignal->clear(); return; } -void KviDccVideoSJpegCodec::decode(KviDataBuffer * stream,KviDataBuffer * signal) +void KviDccVideoSJpegCodec::decode(KviDataBuffer * stream,KviDataBuffer * videoSignal,KviDataBuffer * textSignal) { static unsigned const char jpg_magic_init[4] = { 0xFF, 0xD8, 0xFF, 0xE0}; //SOI + APP0 static unsigned const char jpg_magic_end[2] = { 0xFF, 0xD9}; //EOI + static unsigned const char *irct_magic_init = (unsigned const char*) "\0<text>\0"; + static unsigned const char *irct_magic_end = (unsigned const char*) "\0</text>\0"; + if(stream->size() < 1)return; - int start = stream->find(jpg_magic_init, 4); - int end = stream->find(jpg_magic_end, 2); - if(start != -1 && end != -1) + + int txtStart = stream->find(irct_magic_init, 8); + int txtEnd = stream->find(irct_magic_end, 9); + + int jpgStart = stream->find(jpg_magic_init, 4); + + if(txtStart!=-1 && txtEnd !=-1 && txtStart<jpgStart) + { + qDebug("a txtStart %d txtEnd %d",txtStart,txtEnd); + stream->remove(txtStart+8); + int len = txtEnd - txtStart -8; //-8 irct_magic_init + if(len>0) + { + textSignal->append(stream->data(), len); + char*txt=(char*)malloc(len+1); + memcpy(txt,stream->data(), len); + txt[len]='\0'; + qDebug("a recv |%s| %d",txt,len); + } + stream->remove(len+9); + } + + jpgStart = stream->find(jpg_magic_init, 4); + int jpgEnd = stream->find(jpg_magic_end, 2); + + if(jpgStart != -1 && jpgEnd != -1) { +// qDebug("jpgStart %d jpgEnd %d",jpgStart,jpgEnd); QImage img; //remove junk before jpeg start - stream->remove(start); - int len = end - start + 1; + stream->remove(jpgStart); + int len = jpgEnd - jpgStart + 1; img.loadFromData(stream->data(), stream->size()); if(!img.isNull()) { - signal->clear(); - signal->append(img.bits(),img.numBytes()); + videoSignal->clear(); + videoSignal->append(img.bits(),img.numBytes()); } stream->remove(len); } + + txtStart = stream->find(irct_magic_init, 8); + txtEnd = stream->find(irct_magic_end, 9); + + if(txtStart!=-1 && txtEnd !=-1) + { + qDebug("b txtStart %d txtEnd %d",txtStart,txtEnd); + stream->remove(txtStart+8); + int len = txtEnd - txtStart -8; //-8 irct_magic_init + if(len>0) + { + textSignal->append(stream->data(), len); + char*txt=(char*)malloc(len+1); + memcpy(txt,stream->data(), len); + txt[len]='\0'; + qDebug("b recv |%s| %d",txt,len); + } + stream->remove(len+9); + } } int KviDccVideoSJpegCodec::encodedFrameSize() @@ -240,23 +290,23 @@ void KviDccVideoTheoraCodec::encodeVideo(KviDataBuffer * videoSignal,KviDataBuff videoSignal->clear(); } -void KviDccVideoTheoraCodec::encodeAudio(KviDataBuffer * audioSignal,KviDataBuffer * stream) +void KviDccVideoTheoraCodec::encodeText(KviDataBuffer * textSignal, KviDataBuffer * stream) { - if(audioSignal->size() < 1) return; + if(textSignal->size() < 1) return; if(!m_pEncoder) m_pEncoder = new KviTheoraEncoder(stream); - m_pEncoder->addAudioFrame(audioSignal->data(),audioSignal->size()); - audioSignal->clear(); + m_pEncoder->addTextFrame(textSignal->data(),textSignal->size()); + textSignal->clear(); } -void KviDccVideoTheoraCodec::decode(KviDataBuffer * stream,KviDataBuffer * signal) +void KviDccVideoTheoraCodec::decode(KviDataBuffer * stream,KviDataBuffer * videoSignal,KviDataBuffer * textSignal) { if(stream->size() < 1)return; if(!m_pDecoder) - m_pDecoder = new KviTheoraDecoder(signal); + m_pDecoder = new KviTheoraDecoder(videoSignal); m_pDecoder->addData(stream); } diff --git a/src/modules/dcc/codec.h b/src/modules/dcc/codec.h index da3c24d18..62d5161c3 100644 --- a/src/modules/dcc/codec.h +++ b/src/modules/dcc/codec.h @@ -65,8 +65,8 @@ protected: public: const char * name(); virtual void encodeVideo(KviDataBuffer * videoSignal, KviDataBuffer * stream); - virtual void encodeAudio(KviDataBuffer * audioSignal, KviDataBuffer * stream); - virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal); + virtual void encodeText(KviDataBuffer * textSignal, KviDataBuffer * stream); + virtual void decode(KviDataBuffer * stream,KviDataBuffer * videoSignal,KviDataBuffer * textSignal); virtual int encodedFrameSize(); virtual int decodedFrameSize(); }; @@ -78,8 +78,8 @@ public: virtual ~KviDccVideoSJpegCodec(); public: virtual void encodeVideo(KviDataBuffer * videoSignal, KviDataBuffer * stream); - virtual void encodeAudio(KviDataBuffer * audioSignal, KviDataBuffer * stream); - virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal); + virtual void encodeText(KviDataBuffer * textSignal, KviDataBuffer * stream); + virtual void decode(KviDataBuffer * stream,KviDataBuffer * videoSignal,KviDataBuffer * textSignal); virtual int encodedFrameSize(); virtual int decodedFrameSize(); }; @@ -92,8 +92,8 @@ public: virtual ~KviDccVideoTheoraCodec(); public: virtual void encodeVideo(KviDataBuffer * videoSignal, KviDataBuffer * stream); - virtual void encodeAudio(KviDataBuffer * audioSignal, KviDataBuffer * stream); - virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal); + virtual void encodeText(KviDataBuffer * textSignal, KviDataBuffer * stream); + virtual void decode(KviDataBuffer * stream,KviDataBuffer * videoSignal,KviDataBuffer * textSignal); virtual int encodedFrameSize(); virtual int decodedFrameSize(); private: diff --git a/src/modules/dcc/libkvidcc.cpp b/src/modules/dcc/libkvidcc.cpp index 261f8ae75..5f252728c 100644 --- a/src/modules/dcc/libkvidcc.cpp +++ b/src/modules/dcc/libkvidcc.cpp @@ -1210,7 +1210,7 @@ static bool dcc_kvs_cmd_video(KviKvsModuleCommandCall * c) if(!kvi_dcc_video_is_valid_codec(szCodec.toUtf8().data())) { - c->warning(__tr2qs_ctx("Invalid codec specified, defaulting to 'sjpeg'","dcc")); + c->warning(__tr2qs_ctx("Invalid codec specified","dcc")); d->szCodec = "sjpeg"; } else { d->szCodec = szCodec; diff --git a/src/modules/dcc/video.cpp b/src/modules/dcc/video.cpp index db0d0a23f..fd1fa8782 100644 --- a/src/modules/dcc/video.cpp +++ b/src/modules/dcc/video.cpp @@ -22,13 +22,15 @@ // //============================================================================= +#include "kvi_settings.h" + #include "video.h" #include "marshal.h" #include "broker.h" -#include "kvi_settings.h" #include "kvi_iconmanager.h" #include "kvi_ircview.h" +#include "kvi_kvs_eventtriggers.h" #include "kvi_locale.h" #include "kvi_out.h" #include "kvi_error.h" @@ -39,10 +41,22 @@ #include "kvi_socket.h" #include "kvi_ircconnection.h" #include "kvi_tal_vbox.h" +#include "kvi_mirccntrl.h" +#include "kvi_frame.h" #include <QToolTip> #include <QByteArray> #include <QBuffer> +#include <QTextDocument> //for Qt::escape + +#ifdef COMPILE_CRYPT_SUPPORT + #include "kvi_crypt.h" + #include "kvi_cryptcontroller.h" +#endif + +#ifdef COMPILE_SSL_SUPPORT + #include "kvi_sslmaster.h" +#endif #include <sys/ioctl.h> @@ -53,36 +67,6 @@ extern KviDccBroker * g_pDccBroker; int g_iVideoDevicePoolInstances=0; #endif -//Check for the *SS Api....we don't want to fail here... - -#ifndef COMPILE_DISABLE_DCC_VOICE - #ifdef HAVE_LINUX_SOUNDCARD_H - #include <linux/soundcard.h> - #else - #ifdef HAVE_SYS_SOUNDCARD_H - #include <sys/soundcard.h> - #else - #ifdef HAVE_SOUNDCARD_H - #include <soundcard.h> - #else - //CAN NOT COMPILE :( - #define COMPILE_DISABLE_DCC_VOICE - #if !defined(COMPILE_ON_WINDOWS) && !defined(COMPILE_ON_MINGW) - #warning "Cannot find the soundcard.h header; you will NOT be able to use DCC Voice" - #endif - #endif - #endif - #endif -#endif - - -//#define KVI_AUDIO_DEVICE "/dev/dsp" -// 32 fragments , 512 bytes -#define KVI_SNDCTL_FRAG_SIZE 0x00B00009 -#define KVI_FRAGMENT_SIZE_IN_BYTES 512 -#define KVI_FORMAT AFMT_S16_LE -#define KVI_NUM_CHANNELS 1 - bool kvi_dcc_video_is_valid_codec(const char * codecName) { if(kvi_strEqualCI("sjpeg",codecName))return true; @@ -111,11 +95,6 @@ KviDccVideoThread::KviDccVideoThread(KviWindow * wnd,kvi_socket_t fd,KviDccVideo m_pInfoMutex = new KviMutex(); m_bRecordingRequestPending = false; -#ifndef COMPILE_DISABLE_DCC_VOICE - m_bSoundcardChecked = false; - m_soundFd = -1; - m_soundFdMode = 0; -#endif //local video input if(!g_pVideoDevicePool) { @@ -146,163 +125,6 @@ KviDccVideoThread::~KviDccVideoThread() #endif } - -bool KviDccVideoThread::checkSoundcard() -{ -#ifdef COMPILE_DISABLE_DCC_VOICE - return false; -#else - bool bOpened = false; - if(m_soundFd == -1) - { - if(!openSoundcard(O_RDONLY))return false; - bOpened = true; - } - - int caps; - - m_bSoundcardChecked = true; - - if(ioctl(m_soundFd,SNDCTL_DSP_GETCAPS,&caps) < 0) - { - postMessageEvent(__tr2qs_ctx("WARNING: failed to check the soundcard duplex capabilities: if this is a half-duplex soundcard, use the DCC VOICE option to force half-duplex algorithm","dcc").toUtf8().data()); - if(bOpened)closeSoundcard(); - return false; - } - - if(!(caps & DSP_CAP_DUPLEX)) - { - m_pOpt->bForceHalfDuplex = true; // the device is half duplex...use it in that way - postMessageEvent(__tr2qs_ctx("Half duplex soundcard detected, you will not be able to talk and listen at the same time","dcc").toUtf8().data()); - } - - if(bOpened)closeSoundcard(); - - return true; -#endif -} - - -bool KviDccVideoThread::openSoundcard(int mode) -{ -#ifdef COMPILE_DISABLE_DCC_VOICE - return false; -#else - int speed = m_pOpt->iSampleRate; - static int chans=KVI_NUM_CHANNELS; - static int fmt=KVI_FORMAT; - static int frag = KVI_SNDCTL_FRAG_SIZE; - - - if(m_soundFd != -1) - { - if(m_soundFdMode == mode)return true; // already open - closeSoundcard(); - } - - m_soundFd = ::open(m_pOpt->szSoundDevice.ptr(),mode | O_NONBLOCK); - if(m_soundFd < 0)return false; - - if(!m_pOpt->bForceHalfDuplex) - { - if(ioctl(m_soundFd,SNDCTL_DSP_SETDUPLEX,0) < 0)goto exit_false; - } - - if(ioctl(m_soundFd,SNDCTL_DSP_SETFRAGMENT,&frag)<0)goto exit_false; - if(ioctl(m_soundFd,SNDCTL_DSP_SETFMT,&fmt)<0)goto exit_false; - if(ioctl(m_soundFd,SNDCTL_DSP_CHANNELS,&chans)<0)goto exit_false; - if(ioctl(m_soundFd,SNDCTL_DSP_SPEED,&speed)<0)goto exit_false; - if(speed != m_pOpt->iSampleRate) - { - KviStr tmp(KviStr::Format,__tr2qs_ctx("WARNING: failed to set the requested sample rate (%d): the device used closest match (%d)","dcc").toUtf8().data(), - m_pOpt->iSampleRate,speed); - postMessageEvent(tmp.ptr()); - } - - // TODO: #warning "We could also support blocking operations mode" - - m_soundFdMode = mode; - - - return true; - -exit_false: - closeSoundcard(); - return false; -#endif -} - -bool KviDccVideoThread::openSoundcardForWriting() -{ -#ifndef COMPILE_DISABLE_DCC_VOICE - return openSoundcardWithDuplexOption(O_WRONLY,O_RDONLY); -#else - return false; -#endif -} - -bool KviDccVideoThread::openSoundcardForReading() -{ -#ifndef COMPILE_DISABLE_DCC_VOICE - return openSoundcardWithDuplexOption(O_RDONLY,O_WRONLY); -#else - return false; -#endif -} - -bool KviDccVideoThread::openSoundcardWithDuplexOption(int openMode,int failMode) -{ -#ifndef COMPILE_DISABLE_DCC_VOICE - if(m_soundFd == -1) - { - // soundcard not open yet...open for write (at least) - if(m_pOpt->bForceHalfDuplex) - { - // Forcing half duplex... (user option or the card does not support full duplex mode) - if(!openSoundcard(openMode))return false; - } else { - // Try read/write open - if(!openSoundcard(O_RDWR)) - { - // half-duplex sound card ? - if(!m_bSoundcardChecked) - { - // We haven't checked the full-duplex support yet... - // Try to open in RDONLY o WRONLY mode - if(!openSoundcard(openMode))return false; - if(!checkSoundcard()) - { - postMessageEvent(__tr2qs_ctx("Ops...failed to test the soundcard capabilities...expect problems...","dcc").toUtf8().data()); - } - } // else the test has been done and it is a full duplex card that is just busy - } - } - } else { - // Hmmm...already open - // If it is open in O_RDWR or O_WRONLY mode...it is ok for us - // but if it is open in O_RDONLY mode...we can do nothing...just wait - return (m_soundFdMode != failMode); - } - - return true; -#else - return false; -#endif -} - -void KviDccVideoThread::closeSoundcard() -{ -#ifndef COMPILE_DISABLE_DCC_VOICE - if(m_soundFd != -1) - { - ::close(m_soundFd); - m_soundFd = -1; - m_soundFdMode = 0; - } -#endif -} - - bool KviDccVideoThread::readWriteStep() { #ifndef COMPILE_DISABLE_DCC_VIDEO @@ -320,7 +142,7 @@ bool KviDccVideoThread::readWriteStep() if(readLen > 0) { if(readLen < 4096)m_inFrameBuffer.resize(actualSize + readLen); - m_pOpt->pCodec->decode(&m_inFrameBuffer,&m_inSignalBuffer); + m_pOpt->pCodec->decode(&m_inFrameBuffer,&m_videoInSignalBuffer,&m_textInSignalBuffer); //#warning "A maximum length for the signal buffer is actually needed!!!" } else { bCanRead=false; @@ -355,10 +177,10 @@ bool KviDccVideoThread::videoStep() // Are we playing ? if(m_bPlaying) { - if(m_inSignalBuffer.size() > 0) + if(m_videoInSignalBuffer.size() > 0) { - QImage img(m_inSignalBuffer.data(), 320, 240, 1280, QImage::Format_ARGB32); -// qDebug("IMG data %p size %d", m_inSignalBuffer.data(), m_inSignalBuffer.size()); + QImage img(m_videoInSignalBuffer.data(), 320, 240, 1280, QImage::Format_ARGB32); +// qDebug("IMG data %p size %d", m_videoInSignalBuffer.data(), m_videoInSignalBuffer.size()); if(!img.isNull()) m_inImage = img; } @@ -381,167 +203,100 @@ bool KviDccVideoThread::videoStep() return true; } -bool KviDccVideoThread::audioStep() +bool KviDccVideoThread::textStep() { #ifndef COMPILE_DISABLE_DCC_VIDEO -#ifndef COMPILE_DISABLE_DCC_VOICE // Are we playing ? -/* if(m_bPlaying) { - // Do we have something to write ? - audio_buf_info info; - if(m_inSignalBuffer.size() > 0) + if(m_textInSignalBuffer.size() > 0) { - // Get the number of fragments that can be written to the soundcard without blocking - - if(ioctl(m_soundFd,SNDCTL_DSP_GETOSPACE,&info) < 0) - { - debug("get o space failed"); - info.bytes = KVI_FRAGMENT_SIZE_IN_BYTES; // dummy... if this is not correct...well...we will block for 1024/16000 of a sec - info.fragments = 1; - info.fragsize = KVI_FRAGMENT_SIZE_IN_BYTES; - } - if(info.fragments > 0) - { - int toWrite = info.fragments * info.fragsize; - //debug("Can write %d bytes",toWrite); - if(m_inSignalBuffer.size() < toWrite)toWrite = m_inSignalBuffer.size(); - int written = write(m_soundFd,m_inSignalBuffer.data(),toWrite); - if(written > 0)m_inSignalBuffer.remove(written); - else { -//#warning "Do something for -1 here ?" -//#warning "Usleep ?" - } - } //else { - // No stuff can be written...we are running too fast ? - // m_uSleepTime += 100; // sleep for a while - //} - } else { - // hmmmm....playing , but nothing to write , possible underrun or EOF - // a nice idea would be to use SNDCTL_DSP_GETODELAY here... - // but it appears to be broken on some audio devices - if(ioctl(m_soundFd,SNDCTL_DSP_GETOSPACE,&info) < 0)info.fragstotal = info.fragments; // dummy...but what should we do ? - if(info.fragstotal == info.fragments) - { - // underrun or EOF: close the device - stopPlaying(); - } - } - } else { - // do we have anything to play ? - if(m_inSignalBuffer.size() > 0) - { - if(m_inSignalBuffer.size() >= m_pOpt->iPreBufferSize) - { - // yep...stuff to play... open the soundcard , if possible - startPlaying(); - - m_iLastSignalBufferSize = m_inSignalBuffer.size(); - } else { - // have stuff to play , but it's not enough to fill the pre-buffer - // - struct timeval tv; - gettimeofday(&tv,0); - - long int sigBufferTime = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - - if(m_inSignalBuffer.size() == m_iLastSignalBufferSize) - { - // the same signal buffer size... check the time - // m_pOpt->iPreBufferSize / 16 gives us the preBufferTime in msecs - // we calc the remaining preBufferTime by subtracting the - // size of buffer already filled and we also add 50 milliseconds... smart heuristic - int preBufferTime = ((m_pOpt->iPreBufferSize - m_iLastSignalBufferSize) / 16) + 50; - // if the buffer size hasn't changed since preBufferTime - // it's time to start playing anyway, since there is - // either a network stall or it was just a really short data stream - if((sigBufferTime - m_iLastSignalBufferTime) > preBufferTime) - { - startPlaying(); - if(m_bPlaying)m_iLastSignalBufferSize = 0; - } - } else { - // signal buffer size differs...we have received new packets - // and still pre-buffering - m_iLastSignalBufferSize = m_inSignalBuffer.size(); - m_iLastSignalBufferTime = sigBufferTime; - } - } + KviDccThreadIncomingData data; + data.iLen = m_textInSignalBuffer.size(); + data.buffer = (char*) kvi_malloc(data.iLen); + memcpy(data.buffer, m_textInSignalBuffer.data(), data.iLen); + handleIncomingData(&data,false); + m_textInSignalBuffer.clear(); } } -*/ + // Are we recording ? if(m_bRecording) { - fd_set rs; - FD_ZERO(&rs); - FD_SET(m_soundFd,&rs); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 10; - int ret = select(m_soundFd + 1,&rs,0,0,&tv); - if(ret > 0) + if(((KviDccVideo*)parent())->m_tmpTextDataOut.size()) { - // This is rather easy... - audio_buf_info info; - if(ioctl(m_soundFd,SNDCTL_DSP_GETISPACE,&info) < 0) - { - debug("Ispace failed"); - info.fragments = 0; // dummy... - info.bytes = 0; - } + m_textOutSignalBuffer.append((const unsigned char*) ((KviDccVideo*)parent())->m_tmpTextDataOut.constData(), ((KviDccVideo*)parent())->m_tmpTextDataOut.size()); + ((KviDccVideo*)parent())->m_tmpTextDataOut.clear(); + } - //debug("INFO: fragments: %d, fragstotal: %d, fragsize: %d, bytes: %d",info.fragments,info.fragstotal,info.fragsize,info.bytes); + if(m_textOutSignalBuffer.size()) + m_pOpt->pCodec->encodeText(&m_textOutSignalBuffer,&m_outFrameBuffer); + } - if(info.fragments == 0 && info.bytes == 0) - { - // force a dummy read: the device needs to be triggered - info.fragments = 1; - } +#endif // !COMPILE_DISABLE_DCC_VIDEO + return true; +} - if(info.fragments > 0) +bool KviDccVideoThread::handleIncomingData(KviDccThreadIncomingData * data,bool bCritical) +{ + __range_valid(data->iLen); + __range_valid(data->buffer); + char * aux = data->buffer; + char * end = data->buffer + data->iLen; + while(aux != end) + { + if((*aux == '\n') || (*aux == '\0')) + { + KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_DATA); + // The left part is len chars long + int len = aux - data->buffer; +// debug("LEN = %d, iLen = %d",len,data->iLen); +//#warning "DO IT BETTER (the \r cutting)" + KviStr * s = new KviStr(data->buffer,len); + if(s->lastCharIs('\r'))s->cutRight(1); + e->setData(s); + // but we cut also \n (or \0) + ++aux; + // so len += 1; --> new data->iLen -= len; + data->iLen -= (len + 1); +// debug("iLen now = %d",data->iLen); + __range_valid(data->iLen >= 0); + if(data->iLen > 0) { - int oldSize = m_audioOutSignalBuffer.size(); - int available = info.fragments * info.fragsize; - m_audioOutSignalBuffer.addSize(available); - int readed = read(m_soundFd,m_audioOutSignalBuffer.data() + oldSize,available); - - if(readed < available) - { - // huh ? ...error ? - if(readed >= 0)m_audioOutSignalBuffer.resize(oldSize + readed); - else { - if((errno == EINTR) || (errno == EAGAIN)) - { - m_audioOutSignalBuffer.resize(oldSize); - } else { -//#warning "Critical error...do something reasonable!" - m_audioOutSignalBuffer.resize(oldSize); - } - } - } -/* - debug("Signal buffer:"); - for(int i=0;i<200;i+=2) - { - if(i >= m_outSignalBuffer.size())break; - printf("%04x ",*(((unsigned short *)(m_outSignalBuffer.data() + i)))); - if((i % 6) == 0)printf("\n"); - } - debug("END\n"); -*/ - m_pOpt->pCodec->encodeAudio(&m_audioOutSignalBuffer,&m_outFrameBuffer); + // memmove the remaining part to the beginning + // aux points after \n or \0 + kvi_memmove(data->buffer,aux,data->iLen); + data->buffer = (char *)kvi_realloc(data->buffer,data->iLen); + end = data->buffer + data->iLen; + aux = data->buffer; + } else { + // no more data in the buffer + __range_valid(data->iLen == 0); + kvi_free(data->buffer); + data->buffer = end = aux = 0; } - }// else { - // Nothing to read - // m_uSleepTime += 100; - // } + postEvent(parent(),e); + } else aux++; +// debug("PASSING CHAR %c",*aux); + } + // now aux == end + if(bCritical) + { + // need to flush everything... + if(data->iLen > 0) + { + // in the last part there are no NULL and \n chars + KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_DATA); + KviStr * s = new KviStr(data->buffer,data->iLen); + if(s->lastCharIs('\r'))s->cutRight(1); + e->setData(s); + data->iLen = 0; + kvi_free(data->buffer); + data->buffer = 0; + postEvent(parent(),e); + } } - -#endif // !COMPILE_DISABLE_DCC_VOICE -#endif // !COMPILE_DISABLE_DCC_VIDEO return true; } @@ -550,10 +305,6 @@ void KviDccVideoThread::startRecording() #ifndef COMPILE_DISABLE_DCC_VIDEO //debug("Start recording"); if(m_bRecording)return; // already started - - //FIXME this is mandatory only for audio! - openSoundcardForReading(); - { // debug("Posting event"); @@ -581,8 +332,6 @@ void KviDccVideoThread::stopRecording() postEvent(KviDccThread::parent(),e); m_bRecording = false; - //FIXME this is mandatory only if we are using audio - if(!m_bPlaying)closeSoundcard(); #endif } @@ -591,15 +340,12 @@ void KviDccVideoThread::startPlaying() #ifndef COMPILE_DISABLE_DCC_VIDEO //debug("Start playing"); if(m_bPlaying)return; - //FIXME this is mandatory only if we are using audio - openSoundcardForWriting(); - //if() - { - 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; - } + + 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 } @@ -612,10 +358,7 @@ void KviDccVideoThread::stopPlaying() 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; - //FIXME this is mandatory only if we are using audio - if(!m_bRecording)closeSoundcard(); #endif } @@ -647,14 +390,14 @@ void KviDccVideoThread::run() } if(!readWriteStep())goto exit_dcc; - //if(!videoStep() || !audioStep())goto exit_dcc; if(!videoStep())goto exit_dcc; - + if(!textStep())goto exit_dcc; + m_pInfoMutex->lock(); m_pInfoMutex->unlock(); //if(m_uSleepTime)usleep(m_uSleepTime); -// qDebug("in %d out %d in_sig %d out_sig %d", m_inFrameBuffer.size(), m_outFrameBuffer.size(), m_inSignalBuffer.size(), m_videoOutSignalBuffer.size()); +// qDebug("in %d out %d in_sig %d out_sig %d", m_inFrameBuffer.size(), m_outFrameBuffer.size(), m_videoInSignalBuffer.size(), m_videoOutSignalBuffer.size()); usleep(200); // Start recording if the request was not fulfilled yet @@ -670,13 +413,31 @@ exit_dcc: } KviDccVideo::KviDccVideo(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name) -: KviDccWindow(KVI_WINDOW_TYPE_DCCVOICE,pFrm,name,dcc) +: KviDccWindow(KVI_WINDOW_TYPE_DCCVIDEO,pFrm,name,dcc) { m_pDescriptor = dcc; m_pSlaveThread = 0; m_pszTarget = 0; - m_pLayout = new QGridLayout(); + m_pLayout = new QGridLayout(this); + + m_pButtonBox = new KviTalHBox(this); + + m_pLabel = new KviThemedLabel(m_pButtonBox, this, "dcc_chat_label"); + m_pLabel->setText(name); + m_pButtonBox->setStretchFactor(m_pLabel,1); + + m_pButtonContainer= new KviTalHBox(m_pButtonBox); + createTextEncodingButton(m_pButtonContainer); + +#ifdef COMPILE_CRYPT_SUPPORT + createCryptControllerButton(m_pButtonContainer); +#endif + m_pLayout->addWidget(m_pButtonBox, 0, 0, 1, 3); + + m_pIrcView = new KviIrcView(this,pFrm,this); + connect(m_pIrcView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked())); + m_pInput = new KviInput(this); //remote video m_pInVideoLabel = new QLabel(); @@ -685,7 +446,7 @@ KviDccVideo::KviDccVideo(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name m_pInVideoLabel->setFrameShape(QFrame::Box); m_pInVideoLabel->setScaledContents(true); m_pInVideoLabel->setAlignment(Qt::AlignCenter); - m_pLayout->addWidget(m_pInVideoLabel, 0, 0, 10, 1); + m_pLayout->addWidget(m_pInVideoLabel, 1, 0, 6, 1); //local video m_pOutVideoLabel = new QLabel(); @@ -694,32 +455,38 @@ KviDccVideo::KviDccVideo(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name m_pOutVideoLabel->setFrameShape(QFrame::Box); m_pOutVideoLabel->setScaledContents(true); m_pOutVideoLabel->setAlignment(Qt::AlignCenter); - m_pLayout->addWidget(m_pOutVideoLabel, 11, 0, 10, 1); + m_pLayout->addWidget(m_pOutVideoLabel, 1, 1, 6, 1); //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_pVideoLabel[0] = new QLabel(); + m_pVideoLabel[0]->setText(__tr2qs_ctx("Video device:","dcc")); + m_pLayout->addWidget(m_pVideoLabel[0], 1, 2, 1, 1); m_pCDevices = new QComboBox(); - m_pLayout->addWidget(m_pCDevices, 12, 1, 1, 1); + m_pLayout->addWidget(m_pCDevices, 2, 2, 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_pVideoLabel[1] = new QLabel(); + m_pVideoLabel[1]->setText(__tr2qs_ctx("Input:","dcc")); + m_pLayout->addWidget(m_pVideoLabel[1], 3, 2, 1, 1); m_pCInputs = new QComboBox(); - m_pLayout->addWidget(m_pCInputs, 14, 1, 1, 1); + m_pLayout->addWidget(m_pCInputs, 4, 2, 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_pVideoLabel[2] = new QLabel(); + m_pVideoLabel[2]->setText(__tr2qs_ctx("Standard:","dcc")); + m_pLayout->addWidget(m_pVideoLabel[2], 5, 2, 1, 1); m_pCStandards = new QComboBox(); - m_pLayout->addWidget(m_pCStandards, 16, 1, 1, 1); + m_pLayout->addWidget(m_pCStandards, 6, 2, 1, 1); + + m_pLayout->addWidget(m_pIrcView, 7, 0, 1, 3); + m_pLayout->addWidget(m_pInput, 8, 0, 1, 3); + m_pLayout->setRowStretch(7,1); setLayout(m_pLayout); + if(KVI_OPTION_BOOL(KviOption_boolAutoLogDccChat))m_pIrcView->startLogging(); + connect(&m_Timer, SIGNAL(timeout()), this, SLOT(slotUpdateImage()) ); m_Timer.start(200); //5fps @@ -759,14 +526,14 @@ KviDccVideo::~KviDccVideo() delete m_pCStandards; m_pCStandards=0; } - if(m_pLabel[0]) + if(m_pVideoLabel[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; + delete m_pVideoLabel[2]; + delete m_pVideoLabel[1]; + delete m_pVideoLabel[0]; + m_pVideoLabel[2] = 0; + m_pVideoLabel[1] = 0; + m_pVideoLabel[0] = 0; } if(m_pLayout) { @@ -792,6 +559,21 @@ KviDccVideo::~KviDccVideo() } } +void KviDccVideo::textViewRightClicked() +{ + KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatPopupRequest,this,m_pDescriptor->idString()); +} + +void KviDccVideo::triggerCreationEvents() +{ + KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatWindowCreated,this,m_pDescriptor->idString()); +} + +void KviDccVideo::triggerDestructionEvents() +{ + KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatWindowClosing,this,m_pDescriptor->idString()); +} + void KviDccVideo::startConnection() { if(!(m_pDescriptor->bActive)) @@ -867,6 +649,109 @@ QPixmap * KviDccVideo::myIconPtr() return g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCVOICE); } +void KviDccVideo::ownMessage(const QString &text) +{ + if(!m_pSlaveThread) + { + output(KVI_OUT_SYSTEMWARNING,__tr2qs_ctx("Cannot send data: No active connection","dcc")); + return; + } + + QByteArray szData = encodeText(text); + const char * d = szData.data(); + if(!d)return; + +#ifdef COMPILE_CRYPT_SUPPORT + if(cryptSessionInfo()) + { + if(cryptSessionInfo()->bDoEncrypt) + { + if(*d != KVI_TEXT_CRYPTESCAPE) + { + KviStr encrypted; + cryptSessionInfo()->pEngine->setMaxEncryptLen(-1); + switch(cryptSessionInfo()->pEngine->encrypt(d,encrypted)) + { + case KviCryptEngine::Encrypted: + { + KviStr buf(KviStr::Format,"%s\r\n",encrypted.ptr()); + m_tmpTextDataOut.append(buf.ptr(), buf.len()); + m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSGCRYPTED, + m_pDescriptor->szLocalNick.toUtf8().data(),m_pDescriptor->szLocalUser.toUtf8().data(), + m_pDescriptor->szLocalHost.toUtf8().data(),text,KviConsole::NoNotifications); + } + break; + case KviCryptEngine::Encoded: + { + KviStr buf(KviStr::Format,"%s\r\n",encrypted.ptr()); + m_tmpTextDataOut.append(buf.ptr(), buf.len()); + QString encr = decodeText(encrypted.ptr()); + m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG, + m_pDescriptor->szLocalNick.toUtf8().data(),m_pDescriptor->szLocalUser.toUtf8().data(), + m_pDescriptor->szLocalHost.toUtf8().data(),encr,KviConsole::NoNotifications); + } + break; + default: // also case KviCryptEngine::EncryptError + { + QString szErr = cryptSessionInfo()->pEngine->lastError(); + output(KVI_OUT_SYSTEMERROR, + __tr2qs_ctx("The crypto engine was not able to encrypt the current message (%Q): %Q, no data was sent to the remote end","dcc"), + &text,&szErr); + } + break; + } + return; + } else { + d++; //eat the escape code + KviStr buf(KviStr::Format,"%s\r\n",d); + QString tmp = text.right(text.length() - 1); + m_tmpTextDataOut.append(buf.ptr(), buf.len()); + m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG, + m_pDescriptor->szLocalNick.toUtf8().data(),m_pDescriptor->szLocalUser.toUtf8().data(), + m_pDescriptor->szLocalHost.toUtf8().data(),tmp,KviConsole::NoNotifications); + return; + } + } + } +#endif + KviStr buf(KviStr::Format,"%s\r\n",d); + m_tmpTextDataOut.append(buf.ptr(), buf.len()); + m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG, + m_pDescriptor->szLocalNick.toUtf8().data(),m_pDescriptor->szLocalUser.toUtf8().data(), + m_pDescriptor->szLocalHost.toUtf8().data(),text,KviConsole::NoNotifications); +} + +const QString & KviDccVideo::localNick() +{ + // FIXME: This is just a complete HACK + m_szLocalNick = m_pDescriptor->szLocalNick; + return m_szLocalNick; +} + +void KviDccVideo::ownAction(const QString &text) +{ + if(m_pSlaveThread) + { + QString szTmpBuffer; + //see bug ticket #220 + if(KVI_OPTION_BOOL(KviOption_boolStripMircColorsInUserMessages)) + { + szTmpBuffer = KviMircCntrl::stripControlBytes(text); + } else { + szTmpBuffer = text; + } + + QByteArray szData = encodeText(szTmpBuffer); + const char * d = szData.data(); + if(!d)return; + KviStr buf(KviStr::Format,"%cACTION %s%c\r\n",0x01,d,0x01); + m_tmpTextDataOut.append(buf.ptr(), buf.len()); + output(KVI_OUT_ACTION,"%Q %Q",&(m_pDescriptor->szLocalNick),&szTmpBuffer); + } else { + output(KVI_OUT_SYSTEMWARNING,__tr2qs_ctx("Cannot send data: No active connection","dcc")); + } +} + bool KviDccVideo::event(QEvent *e) { if(e->type() == KVI_THREAD_EVENT) @@ -879,12 +764,98 @@ bool KviDccVideo::event(QEvent *e) 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_DATA: + { + KviStr * encoded = ((KviThreadDataEvent<KviStr> *)e)->getData(); + KviStr d=KviStr(decodeText(encoded->ptr())); + if(d.firstCharIs(0x01)) + { + d.cutLeft(1); + if(d.lastCharIs(0x01))d.cutRight(1); + if(kvi_strEqualCIN("ACTION",d.ptr(),6))d.cutLeft(6); + d.stripLeftWhiteSpace(); + output(KVI_OUT_ACTION,"%Q %s",&(m_pDescriptor->szNick),d.ptr()); + if(!hasAttention()) + { + if(KVI_OPTION_BOOL(KviOption_boolFlashDccChatWindowOnNewMessages)) + { + demandAttention(); + } + if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewDccChatMessages)) + { + QString szMsg = "<b>"; + szMsg += m_pDescriptor->szNick; + szMsg += "</b> "; + szMsg += Qt::escape(QString(d.ptr())); + //debug("kvi_sp_ctcp.cpp:975 debug: %s",szMsg.data()); + g_pApp->notifierMessage(this,KVI_OPTION_MSGTYPE(KVI_OUT_ACTION).pixId(),szMsg,KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime)); + } + } + } else { + +#ifdef COMPILE_CRYPT_SUPPORT + if(KviCryptSessionInfo * cinf = cryptSessionInfo()) + { + if(cinf->bDoDecrypt) + { + KviStr decryptedStuff; + switch(cinf->pEngine->decrypt(d.ptr(),decryptedStuff)) + { + case KviCryptEngine::DecryptOkWasEncrypted: + case KviCryptEngine::DecryptOkWasEncoded: + case KviCryptEngine::DecryptOkWasPlainText: + if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage,this,QString(decryptedStuff.ptr()),m_pDescriptor->idString())) + { + m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG, + m_pDescriptor->szNick.toUtf8().data(),m_pDescriptor->szUser.toUtf8().data(), + m_pDescriptor->szHost.toUtf8().data(),decryptedStuff.ptr()); + } + delete encoded; + return true; + break; + + default: // also case KviCryptEngine::DecryptError + { + QString szErr = cinf->pEngine->lastError(); + output(KVI_OUT_SYSTEMERROR, + __tr2qs_ctx("The following message appears to be encrypted, but the crypto engine failed to decode it: %Q","dcc"), + &szErr); + } + break; + } + } + } else { +#endif + // FIXME! + if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage,this,QString(d.ptr()),m_pDescriptor->idString())) + { + m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG, + m_pDescriptor->szNick.toUtf8().data(),m_pDescriptor->szUser.toUtf8().data(), + m_pDescriptor->szHost.toUtf8().data(),d.ptr()); + if(!hasAttention()) + { + if(KVI_OPTION_BOOL(KviOption_boolFlashDccChatWindowOnNewMessages)) + { + demandAttention(); + } + if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewDccChatMessages)) + { + QString szMsg = Qt::escape(QString(d.ptr())); + g_pApp->notifierMessage(this,KVI_SMALLICON_DCCCHATMSG,szMsg,KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime)); + } + } + } +#ifdef COMPILE_CRYPT_SUPPORT + } +#endif + } + delete encoded; + return true; + } + case KVI_DCC_THREAD_EVENT_MESSAGE: { KviStr * str = ((KviThreadDataEvent<KviStr> *)e)->getData(); @@ -929,10 +900,6 @@ 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() @@ -952,10 +919,6 @@ void KviDccVideo::connected() KviDccVideoThreadOptions * opt = new KviDccVideoThreadOptions; opt->pCodec = kvi_dcc_video_get_codec(m_pDescriptor->szCodec.ptr()); - opt->bForceHalfDuplex = KVI_OPTION_BOOL(KviOption_boolDccVoiceForceHalfDuplex); - opt->iPreBufferSize = KVI_OPTION_UINT(KviOption_uintDccVoicePreBufferSize); - opt->szSoundDevice = KVI_OPTION_STRING(KviOption_stringDccVoiceSoundDevice).toUtf8().data(); - opt->iSampleRate = 8000; output(KVI_OUT_DCCMSG,__tr2qs_ctx("Actual codec used is '%s'","dcc"),opt->pCodec->name()); @@ -974,8 +937,6 @@ void KviDccVideo::connected() #endif m_pSlaveThread->start(); - -// m_pTalkButton->setEnabled(true); } void KviDccVideo::stopTalking() @@ -1011,7 +972,7 @@ void KviDccVideo::slotUpdateImage() void KviDccVideo::deviceRegistered(const QString &) { - /* + #ifndef COMPILE_DISABLE_DCC_VIDEO g_pVideoDevicePool->fillDeviceQComboBox(m_pCDevices); g_pVideoDevicePool->fillInputQComboBox(m_pCInputs); @@ -1029,19 +990,16 @@ void KviDccVideo::deviceRegistered(const QString &) // m_Timer.start(200); //5fps // } #endif -#*/ } void KviDccVideo::deviceUnregistered(const QString & ) { -/* #ifndef COMPILE_DISABLE_DCC_VIDEO g_pVideoDevicePool->fillDeviceQComboBox(m_pCDevices); g_pVideoDevicePool->fillInputQComboBox(m_pCInputs); g_pVideoDevicePool->fillStandardQComboBox(m_pCStandards); #endif -*/ } #ifndef COMPILE_USE_STANDALONE_MOC_SOURCES diff --git a/src/modules/dcc/video.h b/src/modules/dcc/video.h index 02f93cd77..628c319d1 100644 --- a/src/modules/dcc/video.h +++ b/src/modules/dcc/video.h @@ -33,6 +33,7 @@ #include "kvi_databuffer.h" #include "kvi_sockettype.h" #include "kvi_tal_hbox.h" +#include "kvi_themedlabel.h" #include <QLabel> #include <QToolButton> @@ -62,10 +63,6 @@ typedef struct _KviDccVideoThreadOptions { QString szVideoDevice; KviDccVideoCodec * pCodec; - bool bForceHalfDuplex; - int iPreBufferSize; - int iSampleRate; - KviStr szSoundDevice; } KviDccVideoThreadOptions; class KviDccVideoThread : public KviDccThread @@ -78,9 +75,10 @@ protected: KviDccVideoThreadOptions * m_pOpt; KviDataBuffer m_outFrameBuffer; KviDataBuffer m_inFrameBuffer; - KviDataBuffer m_inSignalBuffer; + KviDataBuffer m_videoInSignalBuffer; + KviDataBuffer m_textInSignalBuffer; KviDataBuffer m_videoOutSignalBuffer; - KviDataBuffer m_audioOutSignalBuffer; + KviDataBuffer m_textOutSignalBuffer; bool m_bPlaying; bool m_bRecording; bool m_bRecordingRequestPending; @@ -89,30 +87,20 @@ protected: // stuff protected by the mutex: int m_iInputBufferSize; int m_iOutputBufferSize; - //audio - int m_soundFd; - int m_soundFdMode; - bool m_bSoundcardChecked; protected: QImage m_inImage; QImage m_outImage; protected: bool readWriteStep(); bool videoStep(); - bool audioStep(); + bool textStep(); void startRecording(); void stopRecording(); void startPlaying(); void stopPlaying(); inline bool isPlaying() { return m_bPlaying; }; virtual void run(); - //audio - bool checkSoundcard(); - bool openSoundcardWithDuplexOption(int openMode,int failMode); - bool openSoundcard(int mode); - bool openSoundcardForWriting(); - bool openSoundcardForReading(); - void closeSoundcard(); + virtual bool handleIncomingData(KviDccThreadIncomingData *data,bool bCritical); }; @@ -124,6 +112,10 @@ public: KviDccVideo(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name); ~KviDccVideo(); protected: + KviThemedLabel * m_pLabel; + KviTalHBox * m_pButtonBox; + KviTalHBox * m_pButtonContainer; + QLabel *m_pInVideoLabel; QLabel *m_pOutVideoLabel; QComboBox *m_pCDevices; @@ -131,35 +123,34 @@ protected: QComboBox *m_pCStandards; QGridLayout *m_pLayout; QTimer m_Timer; - QLabel * m_pLabel[2]; + QLabel * m_pVideoLabel[2]; QString * m_pszTarget; KviDccVideoThread * m_pSlaveThread; + QByteArray m_tmpTextDataOut; + QString m_szLocalNick; protected: -// virtual void focusInEvent(QFocusEvent *); + virtual void triggerCreationEvents(); + virtual void triggerDestructionEvents(); 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; + virtual const QString & localNick(); + virtual void ownMessage(const QString &text); + virtual void ownAction(const QString &text); 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 &); + void textViewRightClicked(); }; |
