summaryrefslogtreecommitdiffstats
path: root/src/modules/dcc/voice.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/dcc/voice.h')
-rw-r--r--src/modules/dcc/voice.h440
1 files changed, 440 insertions, 0 deletions
diff --git a/src/modules/dcc/voice.h b/src/modules/dcc/voice.h
new file mode 100644
index 00000000..c74c677c
--- /dev/null
+++ b/src/modules/dcc/voice.h
@@ -0,0 +1,440 @@
+#ifndef _VOICE_H_
+#define _VOICE_H_
+//
+// File : voice.h
+// Creation date : Thu Aug 23 04:08:10 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 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 "kvi_window.h"
+
+#include "kvi_databuffer.h"
+#include "kvi_sockettype.h"
+
+#include "codec.h"
+#include "descriptor.h"
+#include "thread.h"
+#include "window.h"
+
+#include "kvi_tal_hbox.h"
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qtimer.h>
+
+#ifndef _DCC_VOICE_CPP_
+ extern bool kvi_dcc_voice_is_valid_codec(const char * codecName);
+#endif
+
+#define KVI_DCC_VOICE_THREAD_ACTION_START_RECORDING 0
+#define KVI_DCC_VOICE_THREAD_ACTION_STOP_RECORDING 1
+#define KVI_DCC_VOICE_THREAD_ACTION_START_PLAYING 2
+#define KVI_DCC_VOICE_THREAD_ACTION_STOP_PLAYING 3
+
+typedef struct _KviDccVoiceThreadOptions
+{
+ bool bForceHalfDuplex;
+ int iPreBufferSize;
+ int iSampleRate;
+ KviStr szSoundDevice;
+ KviDccVoiceCodec * pCodec;
+} KviDccVoiceThreadOptions;
+
+class KviDccVoiceThread : public KviDccThread
+{
+ friend class KviDccVoice;
+public:
+ KviDccVoiceThread(KviWindow * wnd,kvi_socket_t fd,KviDccVoiceThreadOptions * opt);
+ ~KviDccVoiceThread();
+protected:
+// bool m_bUseGsm;
+ KviDccVoiceThreadOptions * m_pOpt;
+ int m_soundFd;
+ int m_soundFdMode;
+ KviDataBuffer m_outFrameBuffer;
+ KviDataBuffer m_inFrameBuffer;
+ KviDataBuffer m_inSignalBuffer;
+ KviDataBuffer m_outSignalBuffer;
+ bool m_bPlaying;
+ bool m_bRecording;
+ bool m_bRecordingRequestPending;
+ bool m_bSoundcardChecked;
+ int m_iLastSignalBufferSize;
+ long m_iLastSignalBufferTime;
+// unsigned int m_uSleepTime;
+ KviMutex * m_pInfoMutex;
+ // stuff protected by the mutex:
+ int m_iInputBufferSize;
+ int m_iOutputBufferSize;
+protected:
+ bool checkSoundcard();
+ bool openSoundcardWithDuplexOption(int openMode,int failMode);
+ bool openSoundcard(int mode);
+ bool openSoundcardForWriting();
+ bool openSoundcardForReading();
+ void closeSoundcard();
+ bool readWriteStep();
+ bool soundStep();
+ void startRecording();
+ void stopRecording();
+ void startPlaying();
+ void stopPlaying();
+ virtual void run();
+};
+
+class KviDccMarshal;
+class QSlider;
+
+class KviDccVoice : public KviDccWindow
+{
+ Q_OBJECT
+public:
+ KviDccVoice(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name);
+ ~KviDccVoice();
+protected:
+ KviTalHBox * m_pHBox;
+ QSlider * m_pVolumeSlider;
+ QLabel * m_pInputLabel;
+ QLabel * m_pOutputLabel;
+ QLabel * m_pRecordingLabel;
+ QLabel * m_pPlayingLabel;
+ QToolButton * m_pTalkButton;
+ QTimer * m_pUpdateTimer;
+ QString m_szTarget;
+ KviDccVoiceThread * 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(KviStr &buffer);
+ void startTalking();
+ void stopTalking();
+ void startConnection();
+ int getMixerVolume(void) const;
+protected slots:
+ void handleMarshalError(int err);
+ void connected();
+ void updateInfo();
+ void startOrStopTalking(bool bStart);
+ void setMixerVolume(int);
+ void connectionInProgress();
+// void stopTalking();
+};
+
+#if 0
+
+
+
+/*
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+CODEC DEFINITION
+
+ Sample rate = samples/sec (ex. 8000)
+ Sample size = bits (ex. 16 bits)
+ Sample endianness = le/be
+
+ Sample compressor = name
+
+ <rate>:<bits>:<endianness>:<compressor>
+
+ 8000:16:le:null
+ 8000:16:le:gsm
+ 8000:16:le:adpcm
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoiceParty
+{
+public:
+ KviVoiceParty(const QString &szNick,const QString &szIp,unsigned short uPort);
+ ~KviVoiceParty();
+protected:
+ QString m_szIp;
+ unsigned short m_uPort;
+ QString m_szNick;
+ KviPointerList<KviVoiceParty> * m_pChildrenTree;
+public:
+ const QString & ip(){ return m_szIp; };
+ unsigned short port(){ return m_uPort; };
+ const QString & nick(){ return m_szNick; };
+ void addChild(KviVoiceParty * pChild);
+};
+
+
+KviVoiceParty::KviVoiceParty(const QString &szNick,const QString &szIp,unsigned short uPort)
+: m_szIp(szIp), m_uPort(uPort), m_szNick(szNick)
+{
+ m_pChildrenTree = 0;
+}
+
+KviVoiceParty::~KviVoiceParty()
+{
+ if(m_pChildrenTree)delete m_pChildrenTree;
+}
+
+void KviVoiceParty::addChild(KviVoiceParty * pChild)
+{
+ if(!m_pChildrenTree)
+ {
+ m_pChildrenTree = new KviPointerList<KviVoiceParty>;
+ m_pChildrenTree->setAutoDelete(true);
+ }
+ m_pChildrenTree->append(pChild);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoiceAudioEncoder
+{
+public:
+ KviVoiceAudioEncoder();
+ ~KviVoiceAudioEncoder();
+public:
+
+};
+
+class KviVoiceAudioDecoder
+{
+public:
+ KviVoiceAudioDecoder();
+ ~KviVoiceAudioDecoder();
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoiceLink
+{
+public:
+ KviVoiceLink(KviVoiceParty * pRemoteParty);
+ ~KviVoiceLink();
+protected:
+ QString m_szId;
+ KviVoiceParty * m_pRemoteParty;
+ KviVoiceAudioEncoder * m_pAudioEncoder;
+ KviVoiceAudioDecoder * m_pAudioDecoder;
+public:
+ const QStirng & id(){ return m_szId; };
+ KviVoiceParty * remoteParty(){ return m_pRemoteParty; };
+};
+
+KviVoiceLink::KviVoiceLink(KviVoiceParty * pRemoteParty)
+{
+ KviQString::sprintf("%Q:%u",&(pRemoteParty->nick()),pRemoteParty->port());
+ m_pRemoteParty = pRemoteParty;
+ m_pAudioEncoder = 0;
+ m_pAudioDecoder = 0;
+}
+
+KviVoiceLink::~KviVoiceLink()
+{
+ delete m_pRemoteParty;
+ if(m_pAudioEncoder)delete m_pAudioEncoder;
+ if(m_pAudioDecoder)delete m_pAudioDecoder;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoice_r8000s16eL_to_r8000s16eB_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eB_to_r8000s16eL_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eL_to_r11025s16eB_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eB_to_r11025s16eL_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eL_to_r8000s16eL_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eL_to_r8000s16eB_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eB_to_r8000s16eL_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eL_to_r11025s16eL_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eL_to_r11025s16eB_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eB_to_r11025s16eL_Transformer
+{
+
+}
+
+
+
+class KviVoiceConference
+{
+public:
+ KviVoiceConference();
+ ~KviVoiceConference();
+public:
+ KviPointerList<KviVoiceLink> * m_pLinks;
+ KviPointerHashTable<QString,KviVoiceLink> *
+ SOCKET m_hUdpSocket;
+ QString m_szLastError;
+
+ unsigned int m_uLocalAudioSampleRate; // samples/sec
+ unsigned int m_uLocalAudioSampleSize; // bits
+ unsigned int m_uLocalAudioEndianness; // 0 = le, 1 = be
+
+public:
+ void conferenceThread();
+protected:
+ void conferenceThreadMain();
+ bool setupUdpSocket();
+};
+
+KviVoiceConference::KviVoiceConference()
+{
+ m_pLinks = new KviPointerList<KviVoiceLink>;
+ m_pLinks->setAutoDelete(true);
+}
+
+KviVoiceConference::~KviVoiceConference()
+{
+ delete m_pLinks;
+}
+
+bool KviVoiceConference::setupUdpSocket()
+{
+ return true;
+}
+
+void KviVoiceConference::shutdownUdpSocket()
+{
+}
+
+void KviVoiceConference::conferenceThreadMain()
+{
+ for(;;)
+ {
+ readAndDecompressIncomingDataForEveryLink();
+
+ mixIncomingDataToASingleStream();
+ playIncomingDataSingleStream();
+
+ readLocalAudioStream();
+
+ foreach(link)
+ {
+ mixLocalAndOtherIncomingDataStreams()
+ compressAndSendOtherIncomingDataStreams()
+ }
+
+ }
+}
+
+void KviVoiceConference::conferenceThread()
+{
+ if(!setupUdpSocket())return;
+
+ conferenceThreadMain();
+
+ shutdownUdpSocket();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+*/
+
+// DCC VOICE NG proto
+
+//
+// tcp control connection
+// --> HELLO: DccVoice protocol header
+// <-- HELLO: DccVoice protocol header
+// --> IACCEPT: Codec-description|CodecId,Codec-description|CodecID,Codec... (in order of preference)
+// <-- IACCEPT: Codec-description|CodecID,Codec-description|CodecId,Codec... (in order of preference)
+// --> MYADDRESS
+// <-- MYADDRESS
+// --> YOURIDIS: <local id for the remote end> (CID)
+// <-- YOURIDIS: <local id for the remote end> (CID)
+
+// Audio is sent in blocks broken in chunks broken in udp packets
+// Each block is a set of consecutive audio chunks that theoretically
+// should be played consecutively.
+// Each packet in a chunk has an ordinal
+// Chunks must be relatively short in order
+// to allow a remote end that looses a packet to
+// synchronize after a short period of time
+// The maximum number of packets in a chunk is 65535 (but a chunk should be no more than 24-32 KBytes in size
+// and in general they should be as small as possible, even one packet per chunk, if the codec allows it)
+// Each chunk should be encoded independently of the others
+// We can switch codec at each chunk (but not at each packet)
+// When some packets are lost we loose the entire chunk
+// A block is completly synchronized in time (unless we loose some chunks: in that case
+// we may decide to synchronize with silence or insert a glitch...)
+// Decoding never depends on the future
+
+// Each packet should be decompressable (eventually dependently on the previous in the chunk)
+// but playable independently
+
+// start UDP stream
+
+// UDP Packet format:
+
+// <magic byte>: byte
+// <magic byte>: byte
+// <local id>: word
+// <payload len>: word
+// <payload>
+
+
+// Payload format:
+
+// <codec id>: word
+// <ordinal in a chunk>: word (0 = beginning of a chunk)
+
+// read raw audio data at sample rate X, sample size Y
+// multiplex data always at this sample rate and sample size
+
+
+#endif
+
+#endif //_VOICE_H_