mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-06 10:15:38 +08:00
284 lines
8.9 KiB
C++
284 lines
8.9 KiB
C++
/* Copyright (C) 2013 VATSIM Community / authors
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef BLACKCORE_VOICE_VATLIB_H
|
|
#define BLACKCORE_VOICE_VATLIB_H
|
|
|
|
#include "voice.h"
|
|
#include "../blackmisc/vaudiodevicelist.h"
|
|
#include "../blackmisc/nwuserlist.h"
|
|
#include <QScopedPointer>
|
|
#include <QMap>
|
|
#include <QSet>
|
|
#include <QString>
|
|
#include <Windows.h>
|
|
|
|
namespace BlackCore
|
|
{
|
|
/*!
|
|
* Vatlib implementation of the IVoiceClient interface.
|
|
*/
|
|
class CVoiceVatlib : public IVoice
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/*!
|
|
* \brief Constructor
|
|
* \param parent
|
|
*/
|
|
CVoiceVatlib(QObject *parent = nullptr);
|
|
|
|
/*!
|
|
* \brief Destructor
|
|
*/
|
|
virtual ~CVoiceVatlib();
|
|
|
|
// Hardware devices
|
|
// TODO: Vatlib supports multiple output devices. That basically means, you could connect
|
|
// to different voice rooms and send their audio to different devices, e.g. ATIS to loudspeakers
|
|
// and ATC to headspeakers. Is not important to implement that now, if ever.
|
|
virtual const BlackMisc::Voice::CAudioDeviceList &audioDevices() const ;
|
|
virtual const BlackMisc::Voice::CAudioDevice defaultAudioInputDevice() const;
|
|
virtual const BlackMisc::Voice::CAudioDevice defaultAudioOutputDevice() const;
|
|
virtual void setInputDevice(const BlackMisc::Voice::CAudioDevice &device);
|
|
virtual void setOutputDevice(const BlackMisc::Voice::CAudioDevice &device);
|
|
|
|
/************************************************
|
|
* SETUP TESTS
|
|
* *********************************************/
|
|
|
|
// Mic tests
|
|
virtual void runSquelchTest();
|
|
virtual void runMicTest();
|
|
|
|
virtual float inputSquelch() const;
|
|
virtual int32_t micTestResult() const;
|
|
virtual QString micTestResultAsString() const;
|
|
|
|
|
|
public slots:
|
|
/*!
|
|
* \brief ATC station callsign, used for voice room designator
|
|
* \param callsign
|
|
*/
|
|
virtual void setMyAircraftCallsign(const BlackMisc::Aviation::CCallsign &callsign);
|
|
|
|
/*!
|
|
* \brief Join a given voice room
|
|
* \param comUnit
|
|
* \param voiceRoom
|
|
*/
|
|
virtual void joinVoiceRoom(const ComUnit comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom);
|
|
|
|
/*!
|
|
* \brief Leave voice room
|
|
* \param comUnit
|
|
*/
|
|
virtual void leaveVoiceRoom(const ComUnit comUnit);
|
|
|
|
/*!
|
|
* \brief Leave all voice rooms
|
|
*/
|
|
virtual void leaveAllVoiceRooms();
|
|
|
|
/*!
|
|
* \brief Room output volume as per COM unit
|
|
* \param comUnit
|
|
* \param volumne
|
|
*/
|
|
virtual void setRoomOutputVolume(const ComUnit comUnit, const int32_t volumne);
|
|
|
|
/*!
|
|
* \brief Start transmitting ("talk")
|
|
* \param comUnit
|
|
*/
|
|
virtual void startTransmitting(const ComUnit comUnit);
|
|
|
|
/*!
|
|
* \brief Stop transmitting ("talk")
|
|
* \param comUnit
|
|
*/
|
|
virtual void stopTransmitting(const ComUnit comUnit);
|
|
|
|
/*!
|
|
* Get COM1/2 voice rooms, which then allows to retrieve information
|
|
* such as connection status etc.
|
|
* \return
|
|
*/
|
|
virtual BlackMisc::Voice::CVoiceRoomList getComVoiceRoomsWithAudioStatus();
|
|
|
|
/*!
|
|
* \brief Voice rooms, const version with no updates
|
|
* \return
|
|
*/
|
|
virtual BlackMisc::Voice::CVoiceRoomList getComVoiceRooms() const
|
|
{
|
|
return this->m_voiceRooms;
|
|
}
|
|
|
|
/*!
|
|
* \brief Get voice room callsings
|
|
* \param comUnit
|
|
* \return
|
|
*/
|
|
virtual QSet<QString> getVoiceRoomCallsings(const ComUnit comUnit) const
|
|
{
|
|
if (!this->m_voiceRoomCallsigns.contains(comUnit)) return QSet<QString>();
|
|
return this->m_voiceRoomCallsigns[comUnit];
|
|
}
|
|
|
|
/************************************************
|
|
* NON API METHODS:
|
|
* The following methods are not part of the
|
|
* public API. They are needed for internal
|
|
* workflow.
|
|
* *********************************************/
|
|
|
|
int32_t queryUserRoomIndex() const {return m_queryUserRoomIndex;}
|
|
|
|
void changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd);
|
|
|
|
signals:
|
|
|
|
/*!
|
|
* \brief User joined or left
|
|
* \param comUnit
|
|
*/
|
|
void userJoinedLeft(const ComUnit comUnit);
|
|
|
|
protected: // QObject overrides
|
|
|
|
/*!
|
|
* \brief Process voice lib
|
|
*/
|
|
virtual void timerEvent(QTimerEvent *);
|
|
|
|
private slots:
|
|
// slots for Mic tests
|
|
void onEndFindSquelch();
|
|
void onEndMicTest();
|
|
|
|
// slot to handle users
|
|
void onUserJoinedLeft(const ComUnit comUnit);
|
|
|
|
private:
|
|
|
|
// shimlib callbacks
|
|
static void onRoomStatusUpdate(Cvatlib_Voice_Simple *obj, Cvatlib_Voice_Simple::roomStatusUpdate upd, int32_t roomIndex, void *cbVar);
|
|
static void onRoomUserReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar);
|
|
static void onInputHardwareDeviceReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar);
|
|
static void onOutputHardwareDeviceReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar);
|
|
|
|
BlackMisc::Voice::CVoiceRoom voiceRoomForUnit(const ComUnit comUnit) const;
|
|
void setVoiceRoomForUnit(const IVoice::ComUnit comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom);
|
|
void addUserInRoom(const ComUnit comUnit, const QString &callsign);
|
|
void removeUserFromRoom(const ComUnit comUnit, const QString &callsign);
|
|
void exceptionDispatcher(const char *caller);
|
|
void enableAudio(const ComUnit comUnit);
|
|
void handlePushToTalk();
|
|
|
|
/*!
|
|
* \brief Deleter
|
|
*/
|
|
struct Cvatlib_Voice_Simple_Deleter
|
|
{
|
|
/*!
|
|
* \brief Cleanup
|
|
* \param pointer
|
|
*/
|
|
static inline void cleanup(Cvatlib_Voice_Simple *pointer)
|
|
{
|
|
pointer->Destroy();
|
|
}
|
|
};
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
/*!
|
|
* \brief Keyboard PTT handling class
|
|
*/
|
|
class CKeyboard
|
|
{
|
|
public:
|
|
// Keyboard hook
|
|
static HHOOK s_keyboardHook;
|
|
static CVoiceVatlib *s_voice;
|
|
static LRESULT CALLBACK keyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam);
|
|
|
|
/*!
|
|
* \brief Constructor, keyboard handling
|
|
*/
|
|
CKeyboard(CVoiceVatlib *vatlib)
|
|
{
|
|
CVoiceVatlib::CKeyboard::s_voice = vatlib;
|
|
CVoiceVatlib::CKeyboard::s_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, CVoiceVatlib::CKeyboard::keyboardProcedure, GetModuleHandle(NULL), 0);
|
|
}
|
|
|
|
/*!
|
|
* Destructor
|
|
*/
|
|
~CKeyboard()
|
|
{
|
|
if (!CVoiceVatlib::CKeyboard::s_keyboardHook) return;
|
|
UnhookWindowsHookEx(CVoiceVatlib::CKeyboard::s_keyboardHook);
|
|
CVoiceVatlib::CKeyboard::s_keyboardHook = nullptr;
|
|
CVoiceVatlib::CKeyboard::s_voice = nullptr;
|
|
}
|
|
};
|
|
|
|
#else
|
|
|
|
/*!
|
|
* \brief Keyboard PTT handling class
|
|
*/
|
|
class CKeyboard
|
|
{
|
|
public:
|
|
static CVoiceVatlib *s_voice;
|
|
|
|
/*!
|
|
* \brief Constructor, keyboard handling
|
|
*/
|
|
CKeyboard(CVoiceVatlib *vatlib)
|
|
{
|
|
CVoiceVatlib::CKeyboard::s_voice = vatlib;
|
|
}
|
|
|
|
/*!
|
|
* Destructor
|
|
*/
|
|
~CKeyboard()
|
|
{
|
|
// void
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
QScopedPointer<Cvatlib_Voice_Simple, Cvatlib_Voice_Simple_Deleter> m_voice;
|
|
BlackMisc::Aviation::CCallsign m_aircraftCallsign; /*!< own callsign to join voice rooms */
|
|
BlackMisc::Voice::CVoiceRoomList m_voiceRooms;
|
|
BlackMisc::Voice::CAudioDeviceList m_devices; /*!< in and output devices */
|
|
QScopedPointer<CKeyboard> m_keyboardPtt; /*!< handler for PTT */
|
|
bool m_pushToTalk; /*!< flag, PTT pressed */
|
|
float m_inputSquelch;
|
|
Cvatlib_Voice_Simple::agc m_micTestResult;
|
|
|
|
typedef QMap<ComUnit, QSet<QString>> TMapRoomCallsigns;
|
|
TMapRoomCallsigns m_voiceRoomCallsigns;
|
|
QSet<QString> m_voiceRoomCallsignsUpdate;
|
|
|
|
// Need to keep the roomIndex because GetRoomUserList does not specifiy it
|
|
// KB: I would remove this approach, it is potentially unsafe
|
|
// Maybe just use 2 "wrapper" callbacks, which then set explicitly the voice room (it is only 2 methods)
|
|
int32_t m_queryUserRoomIndex;
|
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
#endif // guard
|