@ -1,2 +1,4 @@
|
|||||||
*.o
|
*.o
|
||||||
xlxd
|
src/xlxd
|
||||||
|
ambed/ambed
|
||||||
|
ambedtest/ambedtest
|
||||||
|
|||||||
@ -0,0 +1,154 @@
|
|||||||
|
#ifndef __WINDOWS_TYPES__
|
||||||
|
#define __WINDOWS_TYPES__
|
||||||
|
|
||||||
|
#define WINAPI
|
||||||
|
|
||||||
|
typedef unsigned int DWORD;
|
||||||
|
typedef unsigned int ULONG;
|
||||||
|
typedef unsigned short USHORT;
|
||||||
|
typedef unsigned short SHORT;
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef unsigned short WORD;
|
||||||
|
typedef unsigned short WCHAR;
|
||||||
|
typedef unsigned char BYTE;
|
||||||
|
typedef BYTE *LPBYTE;
|
||||||
|
typedef unsigned int BOOL;
|
||||||
|
typedef unsigned char BOOLEAN;
|
||||||
|
typedef unsigned char CHAR;
|
||||||
|
typedef BOOL *LPBOOL;
|
||||||
|
typedef UCHAR *PUCHAR;
|
||||||
|
typedef const char *LPCSTR;
|
||||||
|
typedef char *PCHAR;
|
||||||
|
typedef void *PVOID;
|
||||||
|
typedef void *HANDLE;
|
||||||
|
typedef unsigned int LONG;
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
typedef char *LPSTR;
|
||||||
|
typedef char *LPTSTR;
|
||||||
|
typedef const char *LPCTSTR;
|
||||||
|
typedef DWORD *LPDWORD;
|
||||||
|
typedef WORD *LPWORD;
|
||||||
|
typedef ULONG *PULONG;
|
||||||
|
typedef LONG *LPLONG;
|
||||||
|
typedef PVOID LPVOID;
|
||||||
|
typedef void VOID;
|
||||||
|
typedef USHORT *PUSHORT;
|
||||||
|
typedef unsigned long long int ULONGLONG;
|
||||||
|
|
||||||
|
typedef struct _OVERLAPPED {
|
||||||
|
DWORD Internal;
|
||||||
|
DWORD InternalHigh;
|
||||||
|
union {
|
||||||
|
struct{
|
||||||
|
DWORD Offset;
|
||||||
|
DWORD OffsetHigh;
|
||||||
|
};
|
||||||
|
PVOID Pointer;
|
||||||
|
};
|
||||||
|
HANDLE hEvent;
|
||||||
|
} OVERLAPPED, *LPOVERLAPPED;
|
||||||
|
|
||||||
|
typedef struct _SECURITY_ATTRIBUTES {
|
||||||
|
DWORD nLength;
|
||||||
|
LPVOID lpSecurityDescriptor;
|
||||||
|
BOOL bInheritHandle;
|
||||||
|
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES;
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
// Substitute for HANDLE returned by Windows CreateEvent API.
|
||||||
|
// FT_SetEventNotification expects parameter 3 to be the address
|
||||||
|
// of one of these structures.
|
||||||
|
typedef struct _EVENT_HANDLE
|
||||||
|
{
|
||||||
|
pthread_cond_t eCondVar;
|
||||||
|
pthread_mutex_t eMutex;
|
||||||
|
int iVar;
|
||||||
|
} EVENT_HANDLE;
|
||||||
|
|
||||||
|
typedef struct timeval SYSTEMTIME;
|
||||||
|
typedef struct timeval FILETIME;
|
||||||
|
|
||||||
|
// WaitForSingleObject return values.
|
||||||
|
#define WAIT_ABANDONED 0x00000080L
|
||||||
|
#define WAIT_OBJECT_0 0x00000000L
|
||||||
|
#define WAIT_TIMEOUT 0x00000102L
|
||||||
|
#define WAIT_FAILED 0xFFFFFFFF
|
||||||
|
// Special value for WaitForSingleObject dwMilliseconds parameter
|
||||||
|
#define INFINITE 0xFFFFFFFF // Infinite timeout
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
#ifndef CONST
|
||||||
|
#define CONST const
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// Modem Status Flags
|
||||||
|
//
|
||||||
|
#define MS_CTS_ON ((DWORD)0x0010)
|
||||||
|
#define MS_DSR_ON ((DWORD)0x0020)
|
||||||
|
#define MS_RING_ON ((DWORD)0x0040)
|
||||||
|
#define MS_RLSD_ON ((DWORD)0x0080)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Error Flags
|
||||||
|
//
|
||||||
|
#define CE_RXOVER 0x0001 // Receive Queue overflow
|
||||||
|
#define CE_OVERRUN 0x0002 // Receive Overrun Error
|
||||||
|
#define CE_RXPARITY 0x0004 // Receive Parity Error
|
||||||
|
#define CE_FRAME 0x0008 // Receive Framing error
|
||||||
|
#define CE_BREAK 0x0010 // Break Detected
|
||||||
|
#define CE_TXFULL 0x0100 // TX Queue is full
|
||||||
|
#define CE_PTO 0x0200 // LPTx Timeout
|
||||||
|
#define CE_IOE 0x0400 // LPTx I/O Error
|
||||||
|
#define CE_DNS 0x0800 // LPTx Device not selected
|
||||||
|
#define CE_OOP 0x1000 // LPTx Out-Of-Paper
|
||||||
|
#define CE_MODE 0x8000 // Requested mode unsupported
|
||||||
|
|
||||||
|
//
|
||||||
|
// Events
|
||||||
|
//
|
||||||
|
#define EV_RXCHAR 0x0001 // Any Character received
|
||||||
|
#define EV_RXFLAG 0x0002 // Received certain character
|
||||||
|
#define EV_TXEMPTY 0x0004 // Transmit Queue Empty
|
||||||
|
#define EV_CTS 0x0008 // CTS changed state
|
||||||
|
#define EV_DSR 0x0010 // DSR changed state
|
||||||
|
#define EV_RLSD 0x0020 // RLSD changed state
|
||||||
|
#define EV_BREAK 0x0040 // BREAK received
|
||||||
|
#define EV_ERR 0x0080 // Line status error occurred
|
||||||
|
#define EV_RING 0x0100 // Ring signal detected
|
||||||
|
#define EV_PERR 0x0200 // Printer error occured
|
||||||
|
#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full
|
||||||
|
#define EV_EVENT1 0x0800 // Provider specific event 1
|
||||||
|
#define EV_EVENT2 0x1000 // Provider specific event 2
|
||||||
|
|
||||||
|
//
|
||||||
|
// Escape Functions
|
||||||
|
//
|
||||||
|
#define SETXOFF 1 // Simulate XOFF received
|
||||||
|
#define SETXON 2 // Simulate XON received
|
||||||
|
#define SETRTS 3 // Set RTS high
|
||||||
|
#define CLRRTS 4 // Set RTS low
|
||||||
|
#define SETDTR 5 // Set DTR high
|
||||||
|
#define CLRDTR 6 // Set DTR low
|
||||||
|
#define RESETDEV 7 // Reset device if possible
|
||||||
|
#define SETBREAK 8 // Set the device break line.
|
||||||
|
#define CLRBREAK 9 // Clear the device break line.
|
||||||
|
|
||||||
|
//
|
||||||
|
// PURGE function flags.
|
||||||
|
//
|
||||||
|
#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port.
|
||||||
|
#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port.
|
||||||
|
#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there.
|
||||||
|
#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there.
|
||||||
|
|
||||||
|
#ifndef INVALID_HANDLE_VALUE
|
||||||
|
#define INVALID_HANDLE_VALUE 0xFFFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __WINDOWS_TYPES__ */
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// cambepacket.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// cpacketqueue.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cambepacket.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CAmbePacket::CAmbePacket()
|
||||||
|
{
|
||||||
|
m_uiCodec = CODEC_NONE;
|
||||||
|
::memset(m_uiAmbe, 0, AMBE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmbePacket::CAmbePacket(uint8 uiPid, uint8 uiCodec, const uint8 *Ambe)
|
||||||
|
: CPacket(uiPid)
|
||||||
|
{
|
||||||
|
m_uiCodec = uiCodec;
|
||||||
|
::memcpy(m_uiAmbe, Ambe, AMBE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmbePacket::CAmbePacket(const CAmbePacket &packet)
|
||||||
|
: CPacket(packet)
|
||||||
|
{
|
||||||
|
m_uiCodec = packet.m_uiCodec;
|
||||||
|
::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CAmbePacket::~CAmbePacket()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Set
|
||||||
|
|
||||||
|
void CAmbePacket::SetAmbe(const uint8 *p)
|
||||||
|
{
|
||||||
|
::memcpy(m_uiAmbe, p, AMBE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// cambepacket.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cambepacket_h
|
||||||
|
#define cambepacket_h
|
||||||
|
|
||||||
|
#include "cpacket.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
|
||||||
|
// frame sizes
|
||||||
|
#define AMBE_SIZE 9
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CAmbePacket : public CPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CAmbePacket();
|
||||||
|
CAmbePacket(uint8, uint8, const uint8 *);
|
||||||
|
CAmbePacket(const CAmbePacket &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CAmbePacket();
|
||||||
|
|
||||||
|
// identity
|
||||||
|
bool IsAmbe(void) const { return true; }
|
||||||
|
|
||||||
|
// get
|
||||||
|
uint8 GetCodec(void) const { return m_uiCodec; }
|
||||||
|
uint8 *GetAmbe(void) { return m_uiAmbe; }
|
||||||
|
int GetAmbeSize(void) const { return AMBE_SIZE; }
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetCodec(uint8 c) { m_uiCodec = c; }
|
||||||
|
void SetAmbe(const uint8 *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
uint8 m_uiCodec;
|
||||||
|
uint8 m_uiAmbe[AMBE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cambepacket_h */
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
//
|
||||||
|
// cambeserver.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "ccontroller.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
#include "cambeserver.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CAmbeServer g_AmbeServer;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CAmbeServer::CAmbeServer()
|
||||||
|
{
|
||||||
|
m_bStopThreads = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
#ifdef DEBUG_DUMPFILE
|
||||||
|
m_DebugFile.open("/Users/jeanluc/Desktop/ambed.txt");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CAmbeServer::~CAmbeServer()
|
||||||
|
{
|
||||||
|
m_bStopThreads = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_DUMPFILE
|
||||||
|
m_DebugFile.close();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operation
|
||||||
|
|
||||||
|
bool CAmbeServer::Start(void)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// init interfaces & controller
|
||||||
|
std::cout << "Initializing vocodecs:" << std::endl;
|
||||||
|
ok &= g_Vocodecs.Init();
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Initializing controller" << std::endl;
|
||||||
|
ok &= m_Controller.Init();
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// if ok, start threads
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
m_pThread = new std::thread(CAmbeServer::Thread, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAmbeServer::Stop(void)
|
||||||
|
{
|
||||||
|
// stop controller
|
||||||
|
m_Controller.Close();
|
||||||
|
|
||||||
|
// stop & delete all threads
|
||||||
|
m_bStopThreads = true;
|
||||||
|
|
||||||
|
// stop & delete report threads
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CAmbeServer::Thread(CAmbeServer *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThreads )
|
||||||
|
{
|
||||||
|
This->Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// task
|
||||||
|
|
||||||
|
void CAmbeServer::Task(void)
|
||||||
|
{
|
||||||
|
// and wait a bit
|
||||||
|
CTimePoint::TaskSleepFor(10000);
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// cambeserver.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cambeserver_h
|
||||||
|
#define cambeserver_h
|
||||||
|
|
||||||
|
#include "ccontroller.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CAmbeServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CAmbeServer();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CAmbeServer();
|
||||||
|
|
||||||
|
// operation
|
||||||
|
bool Start(void);
|
||||||
|
void Stop(void);
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void Thread(CAmbeServer *);
|
||||||
|
void Task(void);
|
||||||
|
|
||||||
|
// get
|
||||||
|
const CIp &GetListenIp(void) const { return m_Controller.GetListenIp(); }
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetListenIp(const CIp &ip) { m_Controller.SetListenIp(ip); }
|
||||||
|
|
||||||
|
|
||||||
|
// operator
|
||||||
|
//bool operator ==(const CIp &) const;
|
||||||
|
//operator const char *() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// objects
|
||||||
|
CController m_Controller;
|
||||||
|
|
||||||
|
// threads
|
||||||
|
bool m_bStopThreads;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifdef DEBUG_DUMPFILE
|
||||||
|
std::ofstream m_DebugFile;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cambeserver_h */
|
||||||
@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// cbuffer.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cbuffer.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CBuffer::CBuffer(uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
resize(len);
|
||||||
|
::memcpy(data(), buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// set
|
||||||
|
|
||||||
|
void CBuffer::Set(uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
resize(len);
|
||||||
|
::memcpy(data(), buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Set(const char *sz)
|
||||||
|
{
|
||||||
|
resize(::strlen(sz)+1);
|
||||||
|
::strcpy((char *)data(), sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+len);
|
||||||
|
::memcpy(&(data()[n]), buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint8 ui, int len)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+len);
|
||||||
|
::memset(&(data()[n]), ui, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint8 ui)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+sizeof(uint8));
|
||||||
|
::memcpy(&(data()[n]), &ui, sizeof(uint8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint16 ui)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+sizeof(uint16));
|
||||||
|
::memcpy(&(data()[n]), &ui, sizeof(uint16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint32 ui)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+sizeof(uint32));
|
||||||
|
::memcpy(&(data()[n]), &ui, sizeof(uint32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(const char *sz)
|
||||||
|
{
|
||||||
|
Append((uint8 *)sz, (int)strlen(sz));
|
||||||
|
Append((uint8)0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, uint8 ui)
|
||||||
|
{
|
||||||
|
if ( size() < (i+sizeof(uint8)) )
|
||||||
|
{
|
||||||
|
resize(i+sizeof(uint8));
|
||||||
|
}
|
||||||
|
*(uint8 *)(&(data()[i])) = ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, uint16 ui)
|
||||||
|
{
|
||||||
|
if ( size() < (i+sizeof(uint16)) )
|
||||||
|
{
|
||||||
|
resize(i+sizeof(uint16));
|
||||||
|
}
|
||||||
|
*(uint16 *)(&(data()[i])) = ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, uint32 ui)
|
||||||
|
{
|
||||||
|
if ( size() < (i+sizeof(uint32)) )
|
||||||
|
{
|
||||||
|
resize(i+sizeof(uint32));
|
||||||
|
}
|
||||||
|
*(uint32 *)(&(data()[i])) = ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, const uint8 *ptr, int len)
|
||||||
|
{
|
||||||
|
if ( size() < (i+len) )
|
||||||
|
{
|
||||||
|
resize(i+len);
|
||||||
|
}
|
||||||
|
::memcpy(&(data()[i]), ptr, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operation
|
||||||
|
|
||||||
|
int CBuffer::Compare(uint8 *buffer, int len) const
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
if ( size() >= len )
|
||||||
|
{
|
||||||
|
result = ::memcmp(data(), buffer, len);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CBuffer::Compare(uint8 *buffer, int off, int len) const
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
if ( size() >= (off+len) )
|
||||||
|
{
|
||||||
|
result = ::memcmp(&(data()[off]), buffer, len);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operator
|
||||||
|
|
||||||
|
bool CBuffer::operator ==(const CBuffer &Buffer) const
|
||||||
|
{
|
||||||
|
if ( size() == Buffer.size() )
|
||||||
|
{
|
||||||
|
return (::memcmp((const char *)data(), (const char *)Buffer.data(), size()) == 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBuffer::operator ==(const char *sz) const
|
||||||
|
{
|
||||||
|
if ( size() == ::strlen(sz) )
|
||||||
|
{
|
||||||
|
return (::memcmp((const char *)data(), sz, size()) == 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBuffer::operator const char *() const
|
||||||
|
{
|
||||||
|
return (const char *)data();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// debug
|
||||||
|
|
||||||
|
void CBuffer::DebugDump(std::ofstream &debugout)
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < size(); i++ )
|
||||||
|
{
|
||||||
|
char sz[16];
|
||||||
|
sprintf(sz, "%02X", data()[i]);
|
||||||
|
debugout << sz;
|
||||||
|
if ( i == size()-1 )
|
||||||
|
{
|
||||||
|
debugout << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugout << ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// cbuffer.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cbuffer_h
|
||||||
|
#define cbuffer_h
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CBuffer : public std::vector<uint8>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CBuffer() {};
|
||||||
|
CBuffer(uint8 *, int);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CBuffer() {};
|
||||||
|
|
||||||
|
// set
|
||||||
|
void Set(uint8 *, int);
|
||||||
|
void Set(const char *);
|
||||||
|
void Append(uint8 *, int);
|
||||||
|
void Append(uint8, int);
|
||||||
|
void Append(uint8);
|
||||||
|
void Append(uint16);
|
||||||
|
void Append(uint32);
|
||||||
|
void Append(const char *);
|
||||||
|
void ReplaceAt(int, uint8);
|
||||||
|
void ReplaceAt(int, uint16);
|
||||||
|
void ReplaceAt(int, uint32);
|
||||||
|
void ReplaceAt(int, const uint8 *, int);
|
||||||
|
|
||||||
|
// operation
|
||||||
|
int Compare(uint8 *, int) const;
|
||||||
|
int Compare(uint8 *, int, int) const;
|
||||||
|
|
||||||
|
// operator
|
||||||
|
bool operator ==(const CBuffer &) const;
|
||||||
|
bool operator ==(const char *) const;
|
||||||
|
operator const char *() const;
|
||||||
|
|
||||||
|
// debug
|
||||||
|
void DebugDump(std::ofstream &);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cbuffer_h */
|
||||||
@ -0,0 +1,198 @@
|
|||||||
|
//
|
||||||
|
// ccallsign.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <cctype>
|
||||||
|
#include "ccallsign.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructors
|
||||||
|
|
||||||
|
CCallsign::CCallsign()
|
||||||
|
{
|
||||||
|
// blank all
|
||||||
|
::memset(m_Callsign, ' ', sizeof(m_Callsign));
|
||||||
|
}
|
||||||
|
|
||||||
|
CCallsign::CCallsign(const char *sz)
|
||||||
|
{
|
||||||
|
::memset(m_Callsign, ' ', sizeof(m_Callsign));
|
||||||
|
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)));
|
||||||
|
}
|
||||||
|
|
||||||
|
CCallsign::CCallsign(const CCallsign &callsign)
|
||||||
|
{
|
||||||
|
::memcpy(m_Callsign, callsign.m_Callsign, sizeof(m_Callsign));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// status
|
||||||
|
|
||||||
|
bool CCallsign::IsValid(void) const
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// callsign
|
||||||
|
// first 3 chars are letter or number but cannot be all number
|
||||||
|
int iNum = 0;
|
||||||
|
for ( i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]);
|
||||||
|
if ( IsNumber(m_Callsign[i]) )
|
||||||
|
{
|
||||||
|
iNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valid &= (iNum < 3);
|
||||||
|
// all remaining char are letter, number or space
|
||||||
|
for ( ; i < CALLSIGN_LEN; i++)
|
||||||
|
{
|
||||||
|
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// set
|
||||||
|
|
||||||
|
void CCallsign::SetCallsign(const char *sz)
|
||||||
|
{
|
||||||
|
// set callsign
|
||||||
|
::memset(m_Callsign, ' ', sizeof(m_Callsign));
|
||||||
|
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCallsign::SetCallsign(const uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
// set callsign
|
||||||
|
::memset(m_Callsign, ' ', sizeof(m_Callsign));
|
||||||
|
::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)));
|
||||||
|
for ( int i = 0; i < sizeof(m_Callsign); i++ )
|
||||||
|
{
|
||||||
|
if ( m_Callsign[i] == 0 )
|
||||||
|
{
|
||||||
|
m_Callsign[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// modify
|
||||||
|
|
||||||
|
void CCallsign::PatchCallsign(int off, const uint8 *patch, int len)
|
||||||
|
{
|
||||||
|
if ( off < sizeof(m_Callsign) )
|
||||||
|
{
|
||||||
|
::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// get
|
||||||
|
|
||||||
|
void CCallsign::GetCallsign(uint8 *buffer) const
|
||||||
|
{
|
||||||
|
::memcpy(buffer, m_Callsign, sizeof(m_Callsign));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCallsign::GetCallsignString(char *sz) const
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ )
|
||||||
|
{
|
||||||
|
sz[i] = m_Callsign[i];
|
||||||
|
}
|
||||||
|
sz[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// compare
|
||||||
|
|
||||||
|
bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const
|
||||||
|
{
|
||||||
|
return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const
|
||||||
|
{
|
||||||
|
bool same = true;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
for ( int i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ )
|
||||||
|
{
|
||||||
|
if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) )
|
||||||
|
{
|
||||||
|
same &= (m_Callsign[i] == callsign[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operators
|
||||||
|
|
||||||
|
bool CCallsign::operator ==(const CCallsign &callsign) const
|
||||||
|
{
|
||||||
|
return (::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCallsign::operator const char *() const
|
||||||
|
{
|
||||||
|
char *sz = (char *)(const char *)m_sz;
|
||||||
|
|
||||||
|
// empty
|
||||||
|
::memset(sz, 0, sizeof(m_sz));
|
||||||
|
// callsign
|
||||||
|
sz[CALLSIGN_LEN] = 0;
|
||||||
|
::memcpy(sz, m_Callsign, sizeof(m_Callsign));
|
||||||
|
|
||||||
|
// done
|
||||||
|
return m_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// helper
|
||||||
|
|
||||||
|
bool CCallsign::IsNumber(char c) const
|
||||||
|
{
|
||||||
|
return ((c >= '0') && (c <= '9'));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCallsign::IsLetter(char c) const
|
||||||
|
{
|
||||||
|
return ((c >= 'A') && (c <= 'Z'));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCallsign::IsSpace(char c) const
|
||||||
|
{
|
||||||
|
return (c == ' ');
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// ccallsign.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ccallsign_h
|
||||||
|
#define ccallsign_h
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define CALLSIGN_LEN 8
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CCallsign
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// contructors
|
||||||
|
CCallsign();
|
||||||
|
CCallsign(const char *);
|
||||||
|
CCallsign(const CCallsign &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CCallsign() {};
|
||||||
|
|
||||||
|
// status
|
||||||
|
bool IsValid(void) const;
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetCallsign(const char *);
|
||||||
|
void SetCallsign(const uint8 *, int);
|
||||||
|
|
||||||
|
// modify
|
||||||
|
void PatchCallsign(int, const uint8 *, int);
|
||||||
|
|
||||||
|
// get
|
||||||
|
void GetCallsign(uint8 *) const;
|
||||||
|
void GetCallsignString(char *) const;
|
||||||
|
|
||||||
|
// compare
|
||||||
|
bool HasSameCallsign(const CCallsign &) const;
|
||||||
|
bool HasSameCallsignWithWildcard(const CCallsign &) const;
|
||||||
|
|
||||||
|
// operators
|
||||||
|
bool operator ==(const CCallsign &) const;
|
||||||
|
operator const char *() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// helper
|
||||||
|
bool IsNumber(char) const;
|
||||||
|
bool IsLetter(char) const;
|
||||||
|
bool IsSpace(char) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
char m_Callsign[CALLSIGN_LEN];
|
||||||
|
char m_sz[CALLSIGN_LEN+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* ccallsign_h */
|
||||||
@ -0,0 +1,373 @@
|
|||||||
|
//
|
||||||
|
// ccontroller.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
#include "ccontroller.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CController::CController()
|
||||||
|
{
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
m_Ip = CIp("127.0.0.1");
|
||||||
|
m_uiLastStreamId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CController::~CController()
|
||||||
|
{
|
||||||
|
// close socket
|
||||||
|
m_Socket.Close();
|
||||||
|
|
||||||
|
// close all streams
|
||||||
|
m_Mutex.lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < m_Streams.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_Streams[i];
|
||||||
|
}
|
||||||
|
m_Streams.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Mutex.unlock();
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CController::Init(void)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
// reset stop flag
|
||||||
|
m_bStopThread = false;
|
||||||
|
|
||||||
|
// create our socket
|
||||||
|
ok = m_Socket.Open(m_Ip, TRANSCODER_PORT);
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
// start thread;
|
||||||
|
m_pThread = new std::thread(CController::Thread, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_Ip << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CController::Close(void)
|
||||||
|
{
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CController::Thread(CController *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThread )
|
||||||
|
{
|
||||||
|
This->Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// task
|
||||||
|
|
||||||
|
void CController::Task(void)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
CIp Ip;
|
||||||
|
CCallsign Callsign;
|
||||||
|
uint8 CodecIn;
|
||||||
|
uint8 CodecOut;
|
||||||
|
uint16 StreamId;
|
||||||
|
CStream *Stream;
|
||||||
|
|
||||||
|
// anything coming in from codec client ?
|
||||||
|
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
|
||||||
|
{
|
||||||
|
// crack packet
|
||||||
|
if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) )
|
||||||
|
{
|
||||||
|
std::cout << "Stream Open from " << Callsign << std::endl;
|
||||||
|
|
||||||
|
// try create the stream
|
||||||
|
Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut);
|
||||||
|
|
||||||
|
// send back details
|
||||||
|
if ( Stream != NULL )
|
||||||
|
{
|
||||||
|
EncodeStreamDescrPacket(&Buffer, *Stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EncodeNoStreamAvailablePacket(&Buffer);
|
||||||
|
}
|
||||||
|
m_Socket.Send(Buffer, Ip);
|
||||||
|
}
|
||||||
|
else if ( IsValidClosestreamPacket(Buffer, &StreamId) )
|
||||||
|
{
|
||||||
|
// close the stream
|
||||||
|
CloseStream(StreamId);
|
||||||
|
|
||||||
|
std::cout << "Stream " << (int)StreamId << " closed" << std::endl;
|
||||||
|
}
|
||||||
|
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
|
||||||
|
{
|
||||||
|
//std::cout << "ping - " << Callsign << std::endl;
|
||||||
|
// pong back
|
||||||
|
EncodeKeepAlivePacket(&Buffer);
|
||||||
|
m_Socket.Send(Buffer, Ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HandleTimout/keepalive
|
||||||
|
bool timeout;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// init loop stuffs
|
||||||
|
timeout = false;
|
||||||
|
CStream *stream = NULL;
|
||||||
|
|
||||||
|
// any inactive streams?
|
||||||
|
Lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; (i < m_Streams.size()) && !timeout; i++ )
|
||||||
|
{
|
||||||
|
if ( !(m_Streams[i]->IsActive()) )
|
||||||
|
{
|
||||||
|
timeout = true;
|
||||||
|
stream = m_Streams[i];
|
||||||
|
std::cout << "Stream " << (int)m_Streams[i]->GetId() << " activity timeout " << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock();
|
||||||
|
|
||||||
|
// if any streams timeout, close it
|
||||||
|
// this cannot be done in above loop as it suppress it from array
|
||||||
|
if ( timeout )
|
||||||
|
{
|
||||||
|
CloseStream(stream);
|
||||||
|
}
|
||||||
|
} while (timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// streams management
|
||||||
|
|
||||||
|
CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut)
|
||||||
|
{
|
||||||
|
CStream *stream = NULL;
|
||||||
|
|
||||||
|
// create a new stream
|
||||||
|
m_uiLastStreamId = (m_uiLastStreamId + 1);
|
||||||
|
m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId;
|
||||||
|
stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut);
|
||||||
|
if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) )
|
||||||
|
{
|
||||||
|
std::cout << "Opened stream " << m_uiLastStreamId << std::endl;
|
||||||
|
// and store it
|
||||||
|
Lock();
|
||||||
|
m_Streams.push_back(stream);
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete stream;
|
||||||
|
stream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CController::CloseStream(CStream *stream)
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
{
|
||||||
|
// look for the stream
|
||||||
|
bool found = false;
|
||||||
|
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
|
||||||
|
{
|
||||||
|
// compare object pointers
|
||||||
|
if ( (m_Streams[i]) == stream )
|
||||||
|
{
|
||||||
|
// close it
|
||||||
|
m_Streams[i]->Close();
|
||||||
|
// remove it
|
||||||
|
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
|
||||||
|
delete m_Streams[i];
|
||||||
|
m_Streams.erase(m_Streams.begin()+i);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CController::CloseStream(uint16 StreamId)
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
{
|
||||||
|
// look for the stream
|
||||||
|
bool found = false;
|
||||||
|
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
|
||||||
|
{
|
||||||
|
// compare object pointers
|
||||||
|
if ( (m_Streams[i]->GetId()) == StreamId )
|
||||||
|
{
|
||||||
|
// close it
|
||||||
|
m_Streams[i]->Close();
|
||||||
|
// remove it
|
||||||
|
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
|
||||||
|
delete m_Streams[i];
|
||||||
|
m_Streams.erase(m_Streams.begin()+i);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet decoding helpers
|
||||||
|
|
||||||
|
bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' };
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
|
||||||
|
{
|
||||||
|
// get callsign here
|
||||||
|
Callsign->SetCallsign(&(Buffer.data()[9]), 8);
|
||||||
|
valid = Callsign->IsValid();
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','O','S' };
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
|
||||||
|
{
|
||||||
|
// get callsign here
|
||||||
|
Callsign->SetCallsign(&(Buffer.data()[7]), 8);
|
||||||
|
*CodecIn = Buffer.data()[15];
|
||||||
|
*CodecOut = Buffer.data()[16];
|
||||||
|
|
||||||
|
// valid ?
|
||||||
|
valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut);
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','C','S' };
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) )
|
||||||
|
{
|
||||||
|
// get stream id
|
||||||
|
*StreamId = *(uint16 *)(&Buffer.data()[7]);
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet encoding helpers
|
||||||
|
|
||||||
|
void CController::EncodeKeepAlivePacket(CBuffer *Buffer)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','S','T','D' };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
// id
|
||||||
|
Buffer->Append((uint16)Stream.GetId());
|
||||||
|
// port
|
||||||
|
Buffer->Append((uint16)Stream.GetPort());
|
||||||
|
// codecin
|
||||||
|
Buffer->Append((uint8)Stream.GetCodecIn());
|
||||||
|
// codecout
|
||||||
|
Buffer->Append((uint8)Stream.GetCodecOut());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// codec helpers
|
||||||
|
|
||||||
|
bool CController::IsValidCodecIn(uint8 codec)
|
||||||
|
{
|
||||||
|
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CController::IsValidCodecOut(uint8 codec)
|
||||||
|
{
|
||||||
|
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// ccontroller.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ccontroller_h
|
||||||
|
#define ccontroller_h
|
||||||
|
|
||||||
|
#include "ccallsign.h"
|
||||||
|
#include "cstream.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CController();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CController();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(void);
|
||||||
|
void Close(void);
|
||||||
|
|
||||||
|
// locks
|
||||||
|
void Lock(void) { m_Mutex.lock(); }
|
||||||
|
void Unlock(void) { m_Mutex.unlock(); }
|
||||||
|
|
||||||
|
// get
|
||||||
|
const CIp &GetListenIp(void) const { return (const CIp &)m_Ip; }
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetListenIp(const CIp &ip) { m_Ip = ip; }
|
||||||
|
|
||||||
|
// streams management
|
||||||
|
CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8);
|
||||||
|
void CloseStream(CStream *);
|
||||||
|
void CloseStream(uint16);
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void Thread(CController *);
|
||||||
|
void Task(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// packet decoding helpers
|
||||||
|
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
|
||||||
|
bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *);
|
||||||
|
bool IsValidClosestreamPacket(const CBuffer &, uint16 *);
|
||||||
|
|
||||||
|
// packet encoding helpers
|
||||||
|
void EncodeKeepAlivePacket(CBuffer *);
|
||||||
|
void EncodeStreamDescrPacket(CBuffer *, const CStream &);
|
||||||
|
void EncodeNoStreamAvailablePacket(CBuffer *);
|
||||||
|
|
||||||
|
// codec helpers
|
||||||
|
bool IsValidCodecIn(uint8);
|
||||||
|
bool IsValidCodecOut(uint8);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// control socket
|
||||||
|
CIp m_Ip;
|
||||||
|
CUdpSocket m_Socket;
|
||||||
|
|
||||||
|
// streams
|
||||||
|
uint16 m_uiLastStreamId;
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
std::vector<CStream *> m_Streams;
|
||||||
|
|
||||||
|
// thread
|
||||||
|
bool m_bStopThread;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* ccontroller_h */
|
||||||
@ -0,0 +1,557 @@
|
|||||||
|
//
|
||||||
|
// cftdidevicedescr.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 02/06/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cusb3000interface.h"
|
||||||
|
#include "cusb3003interface.h"
|
||||||
|
#include "cusb3003hrinterface.h"
|
||||||
|
#include "cusb3003df2etinterface.h"
|
||||||
|
#include "cftdidevicedescr.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CFtdiDeviceDescr::CFtdiDeviceDescr(void)
|
||||||
|
{
|
||||||
|
m_bUsed = false;
|
||||||
|
m_uiVid = 0;
|
||||||
|
m_uiPid = 0;
|
||||||
|
::memset(m_szDescription, 0, sizeof(m_szDescription));
|
||||||
|
::memset(m_szSerial, 0, sizeof(m_szSerial));
|
||||||
|
}
|
||||||
|
|
||||||
|
CFtdiDeviceDescr::CFtdiDeviceDescr(uint32 uiVid, uint32 uiPid, const char *szDescription, const char *szSerial)
|
||||||
|
{
|
||||||
|
m_bUsed = false;
|
||||||
|
m_uiVid = uiVid;
|
||||||
|
m_uiPid = uiPid;
|
||||||
|
::strcpy(m_szDescription, szDescription);
|
||||||
|
::strcpy(m_szSerial, szSerial);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr)
|
||||||
|
{
|
||||||
|
m_bUsed = descr.m_bUsed;
|
||||||
|
m_uiVid = descr.m_uiVid;
|
||||||
|
m_uiPid = descr.m_uiPid;
|
||||||
|
::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription));
|
||||||
|
::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// interface factory
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::CreateInterface(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int iNbChs = 0;
|
||||||
|
|
||||||
|
// single channel devices cannot be created alone
|
||||||
|
// three channels devices
|
||||||
|
if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) || // DVSI's USB-3003
|
||||||
|
(::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device
|
||||||
|
(::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3
|
||||||
|
{
|
||||||
|
iNbChs = CreateUsb3003(descr, channels);
|
||||||
|
}
|
||||||
|
// six channels devices
|
||||||
|
else if ( (::strcmp(descr->GetDescription(), "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device
|
||||||
|
{
|
||||||
|
iNbChs = CreateUsb3006(descr, channels);
|
||||||
|
}
|
||||||
|
// twelves channels devices
|
||||||
|
else if ( (::strcmp(descr->GetDescription(), "USB-3012 A") == 0) ) // DVSI's USB-3012
|
||||||
|
{
|
||||||
|
iNbChs = CreateUsb3012(descr, channels);
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
return iNbChs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceDescr *descr2, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int iNbChs = 0;
|
||||||
|
|
||||||
|
// create interface objects
|
||||||
|
if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 1) )
|
||||||
|
{
|
||||||
|
// create 3000-3000 pair
|
||||||
|
CUsb3000Interface *Usb3000A = InstantiateUsb3000(descr1);
|
||||||
|
CUsb3000Interface *Usb3000B = InstantiateUsb3000(descr2);
|
||||||
|
iNbChs = CreatePair(Usb3000A, Usb3000B, channels);
|
||||||
|
}
|
||||||
|
else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 1) )
|
||||||
|
{
|
||||||
|
// create 3003-3000 pair
|
||||||
|
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr1);
|
||||||
|
CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr2);
|
||||||
|
iNbChs = CreatePair(Usb3003, Usb3000, channels);
|
||||||
|
}
|
||||||
|
else if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 3) )
|
||||||
|
{
|
||||||
|
// create 3000-3003 pair
|
||||||
|
CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr1);
|
||||||
|
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr2);
|
||||||
|
iNbChs = CreatePair(Usb3003, Usb3000, channels);
|
||||||
|
}
|
||||||
|
else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 3) )
|
||||||
|
{
|
||||||
|
// create 3003-3003 pair
|
||||||
|
CUsb3003Interface *Usb3003A = InstantiateUsb3003(descr1);
|
||||||
|
CUsb3003Interface *Usb3003B = InstantiateUsb3003(descr2);
|
||||||
|
iNbChs = CreatePair(Usb3003A, Usb3003B, channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return iNbChs;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// get
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::GetNbChannels(void) const
|
||||||
|
{
|
||||||
|
int iNbChs = 0;
|
||||||
|
|
||||||
|
// single channel devices
|
||||||
|
if ( (::strcmp(m_szDescription, "USB-3000") == 0) || // DVSI's USB-3000
|
||||||
|
(::strcmp(m_szDescription, "ThumbDV") == 0) ) // ThumbDV
|
||||||
|
{
|
||||||
|
iNbChs = 1;
|
||||||
|
}
|
||||||
|
// three channels devices
|
||||||
|
else if ( (::strcmp(m_szDescription, "USB-3003") == 0) || // DVSI's USB-3003
|
||||||
|
(::strcmp(m_szDescription, "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device
|
||||||
|
(::strcmp(m_szDescription, "ThumbDV-3") == 0) ) // ThumbDV-3
|
||||||
|
{
|
||||||
|
iNbChs = 3;
|
||||||
|
}
|
||||||
|
// six channels devices
|
||||||
|
else if ( (::strcmp(m_szDescription, "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device
|
||||||
|
{
|
||||||
|
iNbChs = 6;
|
||||||
|
}
|
||||||
|
// twelves channels devices
|
||||||
|
else if ( (::strcmp(m_szDescription, "USB-3012 A") == 0) ) // DVSI's USB-3012
|
||||||
|
{
|
||||||
|
iNbChs = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return iNbChs;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DVSI's USB-3012 factory helper
|
||||||
|
//
|
||||||
|
// This device uses 3 AMBE3003 connected on a single FTDI 4 channels
|
||||||
|
// USB to serial interface. The reset mechanism is based
|
||||||
|
// on DTR and SetBreak. Baudrate is 921600
|
||||||
|
//
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int nStreams = 0;
|
||||||
|
|
||||||
|
// create the interfaces for the four 3003 chips
|
||||||
|
CUsb3003HRInterface *Usb3003A =
|
||||||
|
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), "USB-3012_A", descr->GetSerialNumber());
|
||||||
|
CUsb3003HRInterface *Usb3003B =
|
||||||
|
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), "USB-3012_B", descr->GetSerialNumber());
|
||||||
|
CUsb3003HRInterface *Usb3003C =
|
||||||
|
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), "USB-3012_C", descr->GetSerialNumber());
|
||||||
|
CUsb3003HRInterface *Usb3003D =
|
||||||
|
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), "USB-3012_D", descr->GetSerialNumber());
|
||||||
|
|
||||||
|
// init the interfaces
|
||||||
|
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) &&
|
||||||
|
Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) )
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
// create all channels
|
||||||
|
{
|
||||||
|
// ch1
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch2
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch3
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch4
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch5
|
||||||
|
Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003C->AddChannel(Channel);
|
||||||
|
// ch6
|
||||||
|
Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003C->AddChannel(Channel);
|
||||||
|
// ch7
|
||||||
|
Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003D->AddChannel(Channel);
|
||||||
|
// ch8
|
||||||
|
Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003D->AddChannel(Channel);
|
||||||
|
// ch9
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch10
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch11
|
||||||
|
Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003C->AddChannel(Channel);
|
||||||
|
Usb3003D->AddChannel(Channel);
|
||||||
|
// ch12
|
||||||
|
Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003C->AddChannel(Channel);
|
||||||
|
Usb3003D->AddChannel(Channel);
|
||||||
|
//done
|
||||||
|
nStreams = 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
delete Usb3003A;
|
||||||
|
delete Usb3003B;
|
||||||
|
delete Usb3003C;
|
||||||
|
delete Usb3003D;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return nStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// LX3JL's USB-3006 factory helper
|
||||||
|
//
|
||||||
|
// This device uses 2 AMBE3003 connected on a single FTDI 2 channels
|
||||||
|
// USB to serial interface. The reset mechanism is based
|
||||||
|
// on DTR and software reset. Baudrate is 921600
|
||||||
|
//
|
||||||
|
int CFtdiDeviceDescr::CreateUsb3006(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int nStreams = 0;
|
||||||
|
|
||||||
|
// create the interfaces for the four 3003 chips
|
||||||
|
CUsb3003Interface *Usb3003A =
|
||||||
|
new CUsb3003Interface(descr->GetVid(), descr->GetPid(), "USB-3006_A", descr->GetSerialNumber());
|
||||||
|
CUsb3003Interface *Usb3003B =
|
||||||
|
new CUsb3003Interface(descr->GetVid(), descr->GetPid(), "USB-3006_B", descr->GetSerialNumber());
|
||||||
|
|
||||||
|
// init the interfaces
|
||||||
|
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
// create all channels
|
||||||
|
{
|
||||||
|
// ch1
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch2
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch3
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch4
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch5
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch6
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
//done
|
||||||
|
nStreams = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
delete Usb3003A;
|
||||||
|
delete Usb3003B;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return nStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// USB-3003 factory helpers
|
||||||
|
// DVSI
|
||||||
|
// DF2ET
|
||||||
|
// ThumbDV
|
||||||
|
//
|
||||||
|
// These devices uses a AMBE3003 connected on a single FTDI
|
||||||
|
// USB to serial interface. The reset mechanism is based
|
||||||
|
// on DTR and SetBreak, or software. Baudrate is 921600
|
||||||
|
//
|
||||||
|
int CFtdiDeviceDescr::CreateUsb3003(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int nStreams = 0;
|
||||||
|
|
||||||
|
// create the interfaces for the 3003 chip
|
||||||
|
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr);
|
||||||
|
|
||||||
|
// init the interface
|
||||||
|
if ( (Usb3003 != NULL) && Usb3003->Init(CODEC_NONE) )
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
// create all channels
|
||||||
|
{
|
||||||
|
// ch1
|
||||||
|
Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003->AddChannel(Channel);
|
||||||
|
// ch2
|
||||||
|
Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003->AddChannel(Channel);
|
||||||
|
// done
|
||||||
|
nStreams = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
delete Usb3003;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return nStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 1 ch + 1 ch pair creation
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::CreatePair(CUsb3000Interface *Usb3000A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int nStreams = 0;
|
||||||
|
|
||||||
|
// init the interfaces
|
||||||
|
if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
// create all channels
|
||||||
|
{
|
||||||
|
// ch1
|
||||||
|
Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3000A->AddChannel(Channel);
|
||||||
|
Usb3000B->AddChannel(Channel);
|
||||||
|
// ch2
|
||||||
|
Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3000A->AddChannel(Channel);
|
||||||
|
Usb3000B->AddChannel(Channel);
|
||||||
|
// done
|
||||||
|
nStreams = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
delete Usb3000A;
|
||||||
|
delete Usb3000B;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return nStreams;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 3 ch + 3 ch pair creation
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface *Usb3003B, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int nStreams = 0;
|
||||||
|
|
||||||
|
// init the interfaces
|
||||||
|
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
// create all channels
|
||||||
|
{
|
||||||
|
// ch1
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch2
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch3
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch4
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch5
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// ch6
|
||||||
|
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3003B->AddChannel(Channel);
|
||||||
|
// done
|
||||||
|
nStreams = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
delete Usb3003A;
|
||||||
|
delete Usb3003B;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return nStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 3 ch + 1 ch pair creation
|
||||||
|
|
||||||
|
int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels)
|
||||||
|
{
|
||||||
|
int nStreams = 0;
|
||||||
|
|
||||||
|
// init the interfaces
|
||||||
|
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
// create all channels
|
||||||
|
{
|
||||||
|
// ch1
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch2
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
// ch3
|
||||||
|
Channel = new CVocodecChannel(Usb3003A, 2, Usb3000B, 0, CODECGAIN_AMBEPLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3000B->AddChannel(Channel);
|
||||||
|
// ch4
|
||||||
|
Channel = new CVocodecChannel(Usb3000B, 0, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
|
||||||
|
channels->push_back(Channel);
|
||||||
|
Usb3003A->AddChannel(Channel);
|
||||||
|
Usb3000B->AddChannel(Channel);
|
||||||
|
// done
|
||||||
|
nStreams = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
delete Usb3003A;
|
||||||
|
delete Usb3000B;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return nStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// interface instantiation helpers
|
||||||
|
|
||||||
|
CUsb3003Interface *CFtdiDeviceDescr::InstantiateUsb3003(CFtdiDeviceDescr *descr)
|
||||||
|
{
|
||||||
|
CUsb3003Interface *Usb3003 = NULL;
|
||||||
|
|
||||||
|
// intstantiate the proper version of USB-3003
|
||||||
|
if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) ) // DVSI's USB-3003
|
||||||
|
{
|
||||||
|
// hardware reset, 921600 bps
|
||||||
|
Usb3003 = new CUsb3003HRInterface
|
||||||
|
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
|
||||||
|
}
|
||||||
|
else if ( (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) ) // DF2ET's USB-3003 opensource device
|
||||||
|
{
|
||||||
|
// specific hardware reset, 921600 bps
|
||||||
|
Usb3003 = new CUsb3003DF2ETInterface
|
||||||
|
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
|
||||||
|
}
|
||||||
|
else if ( (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3
|
||||||
|
{
|
||||||
|
// software reset, 921600 bps
|
||||||
|
Usb3003 = new CUsb3003Interface
|
||||||
|
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
return Usb3003;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUsb3000Interface *CFtdiDeviceDescr::InstantiateUsb3000(CFtdiDeviceDescr *descr)
|
||||||
|
{
|
||||||
|
CUsb3000Interface *Usb3000 = NULL;
|
||||||
|
|
||||||
|
// intstantiate the proper version of USB-3000
|
||||||
|
if ( (::strcmp(descr->GetDescription(), "USB-3000") == 0) || // DVSI's USB-3000
|
||||||
|
(::strcmp(descr->GetDescription(), "ThumbDV") == 0) ) // ThumbDV
|
||||||
|
{
|
||||||
|
Usb3000 = new CUsb3000Interface
|
||||||
|
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
return Usb3000;
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
//
|
||||||
|
// cftdidevicedescr.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 02/06/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cftdidevicedescr_h
|
||||||
|
#define cftdidevicedescr_h
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "ftd2xx.h"
|
||||||
|
#include "cvocodecchannel.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define FTDI_MAX_STRINGLENGTH 256
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUsb3000Interface;
|
||||||
|
class CUsb3003Interface;
|
||||||
|
|
||||||
|
class CFtdiDeviceDescr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CFtdiDeviceDescr(void);
|
||||||
|
CFtdiDeviceDescr(uint32, uint32, const char *, const char *);
|
||||||
|
CFtdiDeviceDescr(const CFtdiDeviceDescr &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CFtdiDeviceDescr() {}
|
||||||
|
|
||||||
|
// interface factory
|
||||||
|
static int CreateInterface(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
|
||||||
|
static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
|
||||||
|
|
||||||
|
// get
|
||||||
|
bool IsUsed(void) const { return m_bUsed; }
|
||||||
|
int GetNbChannels(void) const;
|
||||||
|
uint32 GetVid(void) const { return m_uiVid; }
|
||||||
|
uint32 GetPid(void) const { return m_uiPid; }
|
||||||
|
const char *GetDescription(void) const { return m_szDescription; }
|
||||||
|
const char *GetSerialNumber(void) const { return m_szSerial; }
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetUsed(bool used) { m_bUsed = used; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// factory helper
|
||||||
|
static int CreateUsb3012(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
|
||||||
|
static int CreateUsb3006(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
|
||||||
|
static int CreateUsb3003(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
|
||||||
|
static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector<CVocodecChannel *>*);
|
||||||
|
static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*);
|
||||||
|
static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*);
|
||||||
|
static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *);
|
||||||
|
static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// status
|
||||||
|
bool m_bUsed;
|
||||||
|
|
||||||
|
// data
|
||||||
|
uint32 m_uiVid;
|
||||||
|
uint32 m_uiPid;
|
||||||
|
char m_szDescription[FTDI_MAX_STRINGLENGTH];
|
||||||
|
char m_szSerial[FTDI_MAX_STRINGLENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cftdidevicedescr_h */
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// cip.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cip.h"
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructors
|
||||||
|
|
||||||
|
CIp::CIp()
|
||||||
|
{
|
||||||
|
::memset(&m_Addr, 0, sizeof(m_Addr));
|
||||||
|
m_Addr.sin_family = AF_INET;
|
||||||
|
}
|
||||||
|
|
||||||
|
CIp::CIp(const char *sz)
|
||||||
|
{
|
||||||
|
::memset(&m_Addr, 0, sizeof(m_Addr));
|
||||||
|
m_Addr.sin_family = AF_INET;
|
||||||
|
// try xxx.xxx.xxx.xxxx first
|
||||||
|
m_Addr.sin_addr.s_addr = inet_addr(sz);
|
||||||
|
if ( m_Addr.sin_addr.s_addr == INADDR_NONE )
|
||||||
|
{
|
||||||
|
// otherwise try to resolve via dns
|
||||||
|
hostent *record = gethostbyname(sz);
|
||||||
|
if( record != NULL )
|
||||||
|
{
|
||||||
|
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CIp::CIp(const struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CIp::CIp(const CIp &ip)
|
||||||
|
{
|
||||||
|
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// set
|
||||||
|
|
||||||
|
void CIp::SetSockAddr(struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operator
|
||||||
|
|
||||||
|
bool CIp::operator ==(const CIp &ip) const
|
||||||
|
{
|
||||||
|
return ( (ip.m_Addr.sin_family == m_Addr.sin_family) &&
|
||||||
|
(ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) &&
|
||||||
|
(ip.m_Addr.sin_port == m_Addr.sin_port)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
CIp::operator const char *() const
|
||||||
|
{
|
||||||
|
return ::inet_ntoa(m_Addr.sin_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// cip.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cip_h
|
||||||
|
#define cip_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CIp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CIp();
|
||||||
|
//CIp(uint8, uint8, uint8, uint8);
|
||||||
|
CIp(const struct sockaddr_in *);
|
||||||
|
CIp(const char *);
|
||||||
|
CIp(const CIp &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CIp() {};
|
||||||
|
|
||||||
|
// sockaddr
|
||||||
|
void SetSockAddr(struct sockaddr_in *);
|
||||||
|
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
|
||||||
|
|
||||||
|
// operator
|
||||||
|
bool operator ==(const CIp &) const;
|
||||||
|
operator const char *() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
struct sockaddr_in m_Addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cip_h */
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// cpacket.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "cpacket.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructors
|
||||||
|
|
||||||
|
CPacket::CPacket()
|
||||||
|
{
|
||||||
|
m_iCh = 0;
|
||||||
|
m_uiPid = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CPacket::CPacket(uint8 uiPid)
|
||||||
|
{
|
||||||
|
m_iCh = 0;
|
||||||
|
m_uiPid = uiPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPacket::CPacket(const CPacket &packet)
|
||||||
|
{
|
||||||
|
m_iCh = packet.m_iCh;
|
||||||
|
m_uiPid = packet.m_uiPid;
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// cpacket.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 24/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cpacket_h
|
||||||
|
#define cpacket_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CPacket();
|
||||||
|
CPacket(uint8);
|
||||||
|
CPacket(const CPacket &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CPacket() {};
|
||||||
|
|
||||||
|
// identity
|
||||||
|
virtual bool IsVoice(void) const { return false; }
|
||||||
|
virtual bool IsAmbe(void) const { return false; }
|
||||||
|
|
||||||
|
// get
|
||||||
|
int GetChannel(void) const { return m_iCh; }
|
||||||
|
uint8 GetPid(void) const { return m_uiPid; }
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetChannel(int i) { m_iCh = i; }
|
||||||
|
void SetPid(uint8 ui) { m_uiPid = ui; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
int m_iCh;
|
||||||
|
uint8 m_uiPid;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cpacket_h */
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// cpacketqueue.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "cpacketqueue.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CPacketQueue::CPacketQueue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CPacketQueue::~CPacketQueue()
|
||||||
|
{
|
||||||
|
// empty codec queue
|
||||||
|
while ( !empty() )
|
||||||
|
{
|
||||||
|
delete front();
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// purge
|
||||||
|
|
||||||
|
void CPacketQueue::Purge(void)
|
||||||
|
{
|
||||||
|
// this assume queue is already locked
|
||||||
|
while ( !empty() )
|
||||||
|
{
|
||||||
|
delete front();
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// cpacketqueue.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 24/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cpacketqueue_h
|
||||||
|
#define cpacketqueue_h
|
||||||
|
|
||||||
|
#include "cpacket.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CPacketQueue : public std::queue<CPacket *>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CPacketQueue();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
~CPacketQueue();
|
||||||
|
|
||||||
|
// lock
|
||||||
|
void Lock() { m_Mutex.lock(); }
|
||||||
|
void Unlock() { m_Mutex.unlock(); }
|
||||||
|
|
||||||
|
// purge
|
||||||
|
void Purge(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// status
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cpacketqueue_h */
|
||||||
@ -0,0 +1,241 @@
|
|||||||
|
//
|
||||||
|
// cstream.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambeserver.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
#include "cambepacket.h"
|
||||||
|
#include "cstream.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define AMBE_FRAME_SIZE 9
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CStream::CStream()
|
||||||
|
{
|
||||||
|
m_uiId = 0;
|
||||||
|
m_uiPort = 0;
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
m_VocodecChannel = NULL;
|
||||||
|
m_LastActivity.Now();
|
||||||
|
m_iTotalPackets = 0;
|
||||||
|
m_iLostPackets = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 uiCodecIn, uint8 uiCodecOut)
|
||||||
|
{
|
||||||
|
m_uiId = uiId;
|
||||||
|
m_Callsign = Callsign;
|
||||||
|
m_Ip = Ip;
|
||||||
|
m_uiPort = 0;
|
||||||
|
m_uiCodecIn = uiCodecIn;
|
||||||
|
m_uiCodecOut = uiCodecOut;
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
m_VocodecChannel = NULL;
|
||||||
|
m_LastActivity.Now();
|
||||||
|
m_iTotalPackets = 0;
|
||||||
|
m_iLostPackets = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CStream::~CStream()
|
||||||
|
{
|
||||||
|
m_Socket.Close();
|
||||||
|
if ( m_VocodecChannel != NULL )
|
||||||
|
{
|
||||||
|
g_Vocodecs.CloseChannel(m_VocodecChannel);
|
||||||
|
m_VocodecChannel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CStream::Init(uint16 uiPort)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
// reset stop flag
|
||||||
|
m_bStopThread = false;
|
||||||
|
|
||||||
|
// create our socket
|
||||||
|
ok = m_Socket.Open(g_AmbeServer.GetListenIp(), uiPort);
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
// open the vocodecchannel
|
||||||
|
ok &= ((m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut)) != NULL);
|
||||||
|
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
// store port
|
||||||
|
m_uiPort = uiPort;
|
||||||
|
|
||||||
|
// start thread;
|
||||||
|
m_pThread = new std::thread(CStream::Thread, this);
|
||||||
|
|
||||||
|
// init timeout system
|
||||||
|
m_LastActivity.Now();
|
||||||
|
m_iTotalPackets = 0;
|
||||||
|
m_iLostPackets = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Error opening stream : no suitable channel available" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStream::Close(void)
|
||||||
|
{
|
||||||
|
// close everything
|
||||||
|
m_Socket.Close();
|
||||||
|
if ( m_VocodecChannel != NULL )
|
||||||
|
{
|
||||||
|
m_VocodecChannel->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// report
|
||||||
|
std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CStream::Thread(CStream *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThread )
|
||||||
|
{
|
||||||
|
This->Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// task
|
||||||
|
|
||||||
|
void CStream::Task(void)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
static CIp Ip;
|
||||||
|
uint8 uiPid;
|
||||||
|
uint8 Ambe[AMBE_FRAME_SIZE];
|
||||||
|
CAmbePacket *packet;
|
||||||
|
CPacketQueue *queue;
|
||||||
|
|
||||||
|
// anything coming in from codec client ?
|
||||||
|
if ( m_Socket.Receive(&Buffer, &Ip, 1) != -1 )
|
||||||
|
{
|
||||||
|
// crack packet
|
||||||
|
if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) )
|
||||||
|
{
|
||||||
|
// transcode AMBE here
|
||||||
|
m_LastActivity.Now();
|
||||||
|
m_iTotalPackets++;
|
||||||
|
|
||||||
|
// post packet to VocoderChannel
|
||||||
|
packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe);
|
||||||
|
queue = m_VocodecChannel->GetPacketQueueIn();
|
||||||
|
queue->push(packet);
|
||||||
|
m_VocodecChannel->ReleasePacketQueueIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// anything in our queue ?
|
||||||
|
queue = m_VocodecChannel->GetPacketQueueOut();
|
||||||
|
while ( !queue->empty() )
|
||||||
|
{
|
||||||
|
// get the packet
|
||||||
|
packet = (CAmbePacket *)queue->front();
|
||||||
|
queue->pop();
|
||||||
|
// send it to client
|
||||||
|
EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe());
|
||||||
|
m_Socket.Send(Buffer, Ip, m_uiPort);
|
||||||
|
// and done
|
||||||
|
delete packet;
|
||||||
|
}
|
||||||
|
m_VocodecChannel->ReleasePacketQueueOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet decoding helpers
|
||||||
|
|
||||||
|
bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if ( Buffer.size() == 11 )
|
||||||
|
{
|
||||||
|
uint8 codec = Buffer.data()[0];
|
||||||
|
*pid = Buffer.data()[1];
|
||||||
|
::memcpy(ambe, &(Buffer.data()[2]), 9);
|
||||||
|
valid = (codec == GetCodecIn());
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet encodeing helpers
|
||||||
|
|
||||||
|
void CStream::EncodeDvFramePacket(CBuffer *Buffer, uint8 Pid, uint8 *Ambe)
|
||||||
|
{
|
||||||
|
Buffer->clear();
|
||||||
|
Buffer->Append((uint8)GetCodecOut());
|
||||||
|
Buffer->Append((uint8)Pid);
|
||||||
|
Buffer->Append(Ambe, 9);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// cstream.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cstream_h
|
||||||
|
#define cstream_h
|
||||||
|
|
||||||
|
#include "cudpsocket.h"
|
||||||
|
#include "ccallsign.h"
|
||||||
|
#include "cvocodecchannel.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CStream();
|
||||||
|
CStream(uint16, const CCallsign &, const CIp &, uint8, uint8);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CStream();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(uint16);
|
||||||
|
void Close(void);
|
||||||
|
|
||||||
|
// get
|
||||||
|
uint16 GetId(void) const { return m_uiId; }
|
||||||
|
uint16 GetPort(void) const { return m_uiPort; }
|
||||||
|
uint8 GetCodecIn(void) const { return m_uiCodecIn; }
|
||||||
|
uint8 GetCodecOut(void) const { return m_uiCodecOut; }
|
||||||
|
|
||||||
|
// activity timer
|
||||||
|
bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; }
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void Thread(CStream *);
|
||||||
|
void Task(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// packet decoding helpers
|
||||||
|
bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *);
|
||||||
|
|
||||||
|
// packet encodeing helpers
|
||||||
|
void EncodeDvFramePacket(CBuffer *, uint8, uint8 *);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
uint16 m_uiId;
|
||||||
|
CUdpSocket m_Socket;
|
||||||
|
uint16 m_uiPort;
|
||||||
|
uint8 m_uiCodecIn;
|
||||||
|
uint8 m_uiCodecOut;
|
||||||
|
CVocodecChannel *m_VocodecChannel;
|
||||||
|
|
||||||
|
// client details
|
||||||
|
CCallsign m_Callsign;
|
||||||
|
CIp m_Ip;
|
||||||
|
|
||||||
|
// counters
|
||||||
|
int m_iTotalPackets;
|
||||||
|
int m_iLostPackets;
|
||||||
|
|
||||||
|
// activity timer
|
||||||
|
CTimePoint m_LastActivity;
|
||||||
|
|
||||||
|
// thread
|
||||||
|
bool m_bStopThread;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cstream_h */
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// ctimepoint.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CTimePoint::CTimePoint()
|
||||||
|
{
|
||||||
|
m_TimePoint = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operation
|
||||||
|
|
||||||
|
double CTimePoint::DurationSinceNow(void) const
|
||||||
|
{
|
||||||
|
std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now();
|
||||||
|
std::chrono::steady_clock::duration time_span = (Now - m_TimePoint);
|
||||||
|
return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// task
|
||||||
|
|
||||||
|
void CTimePoint::TaskSleepFor(uint ms)
|
||||||
|
{
|
||||||
|
std::chrono::milliseconds timespan(ms);
|
||||||
|
std::this_thread::sleep_for(timespan);
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// ctimepoint.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ctimepoint_h
|
||||||
|
#define ctimepoint_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CTimePoint : public std::chrono::steady_clock::time_point
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CTimePoint();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CTimePoint() {}
|
||||||
|
|
||||||
|
// operation
|
||||||
|
void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); }
|
||||||
|
double DurationSinceNow(void) const;
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void TaskSleepFor(uint);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
std::chrono::steady_clock::time_point m_TimePoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* ctimepoint_h */
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
//
|
||||||
|
// cudpsocket.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cudpsocket.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUdpSocket::CUdpSocket()
|
||||||
|
{
|
||||||
|
m_Socket = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CUdpSocket::~CUdpSocket()
|
||||||
|
{
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// open & close
|
||||||
|
|
||||||
|
bool CUdpSocket::Open(const CIp &ListenIp, uint16 uiPort)
|
||||||
|
{
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
// create socket
|
||||||
|
m_Socket = socket(PF_INET,SOCK_DGRAM,0);
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
// initialize sockaddr struct
|
||||||
|
::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in));
|
||||||
|
m_SocketAddr.sin_family = AF_INET;
|
||||||
|
m_SocketAddr.sin_port = htons(uiPort);
|
||||||
|
m_SocketAddr.sin_addr.s_addr = inet_addr(ListenIp);
|
||||||
|
|
||||||
|
if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 )
|
||||||
|
{
|
||||||
|
fcntl(m_Socket, F_SETFL, O_NONBLOCK);
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(m_Socket);
|
||||||
|
m_Socket = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUdpSocket::Close(void)
|
||||||
|
{
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
close(m_Socket);
|
||||||
|
m_Socket = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// read
|
||||||
|
|
||||||
|
int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
|
||||||
|
{
|
||||||
|
struct sockaddr_in Sin;
|
||||||
|
fd_set FdSet;
|
||||||
|
unsigned int uiFromLen = sizeof(struct sockaddr_in);
|
||||||
|
int iRecvLen = -1;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
// socket valid ?
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
// control socket
|
||||||
|
FD_ZERO(&FdSet);
|
||||||
|
FD_SET(m_Socket, &FdSet);
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
select(m_Socket + 1, &FdSet, 0, 0, &tv);
|
||||||
|
|
||||||
|
// allocate buffer
|
||||||
|
Buffer->resize(UDP_BUFFER_LENMAX);
|
||||||
|
|
||||||
|
// read
|
||||||
|
iRecvLen = (int)recvfrom(m_Socket,
|
||||||
|
(void *)Buffer->data(), UDP_BUFFER_LENMAX,
|
||||||
|
0, (struct sockaddr *)&Sin, &uiFromLen);
|
||||||
|
|
||||||
|
// handle
|
||||||
|
if ( iRecvLen != -1 )
|
||||||
|
{
|
||||||
|
// adjust buffer size
|
||||||
|
Buffer->resize(iRecvLen);
|
||||||
|
|
||||||
|
// get IP
|
||||||
|
Ip->SetSockAddr(&Sin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return iRecvLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// write
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer.data(), Buffer.size(),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const char *Buffer, const CIp &Ip)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer, ::strlen(Buffer),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
temp.GetSockAddr()->sin_port = htons(destport);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer.data(), Buffer.size(),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
temp.GetSockAddr()->sin_port = htons(destport);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer, ::strlen(Buffer),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// cudpsocket.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cudpsocket_h
|
||||||
|
#define cudpsocket_h
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
//#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "cip.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define UDP_BUFFER_LENMAX 1024
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUdpSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CUdpSocket();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
~CUdpSocket();
|
||||||
|
|
||||||
|
// open & close
|
||||||
|
bool Open(const CIp &, uint16);
|
||||||
|
void Close(void);
|
||||||
|
int GetSocket(void) { return m_Socket; }
|
||||||
|
|
||||||
|
// read
|
||||||
|
int Receive(CBuffer *, CIp *, int);
|
||||||
|
|
||||||
|
// write
|
||||||
|
int Send(const CBuffer &, const CIp &);
|
||||||
|
int Send(const CBuffer &, const CIp &, uint16);
|
||||||
|
int Send(const char *, const CIp &);
|
||||||
|
int Send(const char *, const CIp &, uint16);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
int m_Socket;
|
||||||
|
struct sockaddr_in m_SocketAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cudpsocket_h */
|
||||||
@ -0,0 +1,297 @@
|
|||||||
|
//
|
||||||
|
// cusb3000interface.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 21/08/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambepacket.h"
|
||||||
|
#include "cusb3000interface.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// configuration:
|
||||||
|
//
|
||||||
|
// PKT_CHANNEL0 = HYBRID
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUsb3000Interface::CUsb3000Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
|
||||||
|
: CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial)
|
||||||
|
{
|
||||||
|
m_uiChCodec = CODEC_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CUsb3000Interface::Init(uint8 uiOddCodec)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// init the odd channel
|
||||||
|
m_uiChCodec = uiOddCodec;
|
||||||
|
|
||||||
|
// base class
|
||||||
|
ok &= CUsb3xxxInterface::Init();
|
||||||
|
|
||||||
|
// do not create our channels now
|
||||||
|
// this is delegated to caller (CVocodecs) as our channel
|
||||||
|
// may be hybrids between 2 interfaces in case of odd n' of channel device)
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage Channels
|
||||||
|
|
||||||
|
uint8 CUsb3000Interface::GetChannelCodec(int iCh) const
|
||||||
|
{
|
||||||
|
return (iCh == 0) ? m_uiChCodec : CODEC_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage vocodec channels
|
||||||
|
|
||||||
|
CVocodecChannel *CUsb3000Interface::GetChannelWithChannelIn(int iCh)
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel = NULL;
|
||||||
|
bool done = false;
|
||||||
|
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
|
||||||
|
{
|
||||||
|
if ( iCh == 0 )
|
||||||
|
{
|
||||||
|
if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) )
|
||||||
|
{
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVocodecChannel *CUsb3000Interface::GetChannelWithChannelOut(int iCh)
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel = NULL;
|
||||||
|
bool done = false;
|
||||||
|
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
|
||||||
|
{
|
||||||
|
if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
|
||||||
|
{
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// decoder helper
|
||||||
|
|
||||||
|
bool CUsb3000Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
uint8 tag[] = { PKT_HEADER,0x00,0x0B,PKT_CHANNEL };
|
||||||
|
|
||||||
|
if ( (buffer.size() == 15) && (buffer.Compare(tag, sizeof(tag)) == 0))
|
||||||
|
{
|
||||||
|
*ch = 0;
|
||||||
|
packet->SetCodec(m_uiChCodec);
|
||||||
|
packet->SetAmbe(&(buffer.data()[6]));
|
||||||
|
valid = (*ch < GetNbChannels());
|
||||||
|
//std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3000Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if ( (buffer.size() > 6) &&
|
||||||
|
(buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) &&
|
||||||
|
(buffer.data()[4] == PKT_SPEECHD) )
|
||||||
|
{
|
||||||
|
*ch = 0;
|
||||||
|
packet->SetVoice(&(buffer.data()[6]), buffer.data()[5] * 2);
|
||||||
|
valid = (*ch < GetNbChannels());
|
||||||
|
//std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// encoder helpers
|
||||||
|
|
||||||
|
void CUsb3000Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet)
|
||||||
|
{
|
||||||
|
uint size = (uint16)packet->GetAmbeSize() + 2;
|
||||||
|
buffer->clear();
|
||||||
|
buffer->Append((uint8)PKT_HEADER);
|
||||||
|
buffer->Append((uint8)HIBYTE(size));
|
||||||
|
buffer->Append((uint8)LOBYTE(size));
|
||||||
|
buffer->Append((uint8)PKT_CHANNEL);
|
||||||
|
buffer->Append((uint8)(PKT_CHAND));
|
||||||
|
buffer->Append((uint8)(packet->GetAmbeSize()*8));
|
||||||
|
buffer->Append(packet->GetAmbe(), packet->GetAmbeSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUsb3000Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet)
|
||||||
|
{
|
||||||
|
uint16 size = (uint16)packet->GetVoiceSize() + 2;
|
||||||
|
buffer->clear();
|
||||||
|
buffer->Append((uint8)PKT_HEADER);
|
||||||
|
buffer->Append((uint8)HIBYTE(size));
|
||||||
|
buffer->Append((uint8)LOBYTE(size));
|
||||||
|
buffer->Append((uint8)PKT_SPEECH);
|
||||||
|
buffer->Append((uint8)PKT_SPEECHD);
|
||||||
|
buffer->Append((uint8)(packet->GetVoiceSize()/2));
|
||||||
|
buffer->Append(packet->GetVoice(), packet->GetVoiceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// low level
|
||||||
|
|
||||||
|
bool CUsb3000Interface::OpenDevice(void)
|
||||||
|
{
|
||||||
|
FT_STATUS ftStatus;
|
||||||
|
int baudrate = 460800;
|
||||||
|
|
||||||
|
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted.
|
||||||
|
ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
|
||||||
|
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
|
||||||
|
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
|
||||||
|
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
|
||||||
|
if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetRts (m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; }
|
||||||
|
|
||||||
|
//for usb-3012 pull DTR high to take AMBE3003 out of reset.
|
||||||
|
//for other devices noting is connected to DTR so it is a dont care
|
||||||
|
ftStatus = FT_ClrDtr(m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
|
||||||
|
|
||||||
|
// done
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3000Interface::ResetDevice(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int len;
|
||||||
|
char rxpacket[100];
|
||||||
|
char zeropacket[10] =
|
||||||
|
{
|
||||||
|
0,0,0,0,0,0,0,0,0,0
|
||||||
|
};
|
||||||
|
char txpacket[7] =
|
||||||
|
{
|
||||||
|
PKT_HEADER,
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
PKT_RESET,
|
||||||
|
PKT_PARITYBYTE,
|
||||||
|
3 ^ PKT_RESET ^ PKT_PARITYBYTE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet.
|
||||||
|
//first send 350 zeros in case, the chip's receive state is still waiting for characters
|
||||||
|
//if we send more than needed, the exta characters will just get discarded since they do not match the header byte
|
||||||
|
//after that we send PKT_RESET to reset the device
|
||||||
|
//As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it.
|
||||||
|
|
||||||
|
for ( int i = 0; i < 35 ; i++ )
|
||||||
|
{
|
||||||
|
FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// write soft-reset packet
|
||||||
|
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
|
||||||
|
{
|
||||||
|
// read reply
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
|
||||||
|
ok = ((len == 5) && (rxpacket[4] == PKT_READY));
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
std::cout << "USB-3000 soft reset failed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3000Interface::ConfigureDevice(void)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 };
|
||||||
|
uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 };
|
||||||
|
|
||||||
|
// configure the channel for desired codec
|
||||||
|
switch ( m_uiChCodec )
|
||||||
|
{
|
||||||
|
case CODEC_AMBEPLUS:
|
||||||
|
ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambeplus, 0, 0);
|
||||||
|
break;
|
||||||
|
case CODEC_AMBE2PLUS:
|
||||||
|
ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambe2plus, 0, 0);
|
||||||
|
break;
|
||||||
|
case CODEC_NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// cusb3000interface.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 21/08/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cusb3000interface_h
|
||||||
|
#define cusb3000interface_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "ftd2xx.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
#include "cusb3xxxinterface.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define USB3000_NB_CH 1
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUsb3000Interface : public CUsb3xxxInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CUsb3000Interface(uint32, uint32, const char *, const char *);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CUsb3000Interface() {}
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(uint8);
|
||||||
|
|
||||||
|
// manage channels
|
||||||
|
int GetNbChannels(void) const { return USB3000_NB_CH; }
|
||||||
|
uint8 GetChannelCodec(int) const;
|
||||||
|
|
||||||
|
// manage vocodec channels
|
||||||
|
CVocodecChannel *GetChannelWithChannelIn(int);
|
||||||
|
CVocodecChannel *GetChannelWithChannelOut(int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// decoder helper
|
||||||
|
bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *);
|
||||||
|
bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *);
|
||||||
|
|
||||||
|
// encoder helpers
|
||||||
|
void EncodeChannelPacket(CBuffer *, int, CAmbePacket *);
|
||||||
|
void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *);
|
||||||
|
|
||||||
|
// low level
|
||||||
|
bool OpenDevice(void);
|
||||||
|
bool ResetDevice(void);
|
||||||
|
bool ConfigureDevice(void);
|
||||||
|
|
||||||
|
// data
|
||||||
|
uint8 m_uiChCodec;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cusb3000interface_h */
|
||||||
@ -0,0 +1,164 @@
|
|||||||
|
//
|
||||||
|
// cusb3003df2etinterface.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET) on 03/11/2017.
|
||||||
|
// Copyright © 2017 Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Created by Florian Wolters (DF2ET) on 03/11/2017.
|
||||||
|
// Copyright © 2017 Florian Wolters (DF2ET). All rights reserved.
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambepacket.h"
|
||||||
|
#include "cusb3003df2etinterface.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUsb3003DF2ETInterface::CUsb3003DF2ETInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
|
||||||
|
: CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// low level
|
||||||
|
|
||||||
|
bool CUsb3003DF2ETInterface::OpenDevice(void)
|
||||||
|
{
|
||||||
|
FT_STATUS ftStatus;
|
||||||
|
int baudrate = 921600;
|
||||||
|
|
||||||
|
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted.
|
||||||
|
ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
|
||||||
|
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
|
||||||
|
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
|
||||||
|
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
|
||||||
|
if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetRts (m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; }
|
||||||
|
|
||||||
|
// for DF2ET-3003 interface pull DTR low to take AMBE3003 out of reset.
|
||||||
|
ftStatus = FT_SetDtr( m_FtdiHandle );
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetDtr", ftStatus); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
|
||||||
|
|
||||||
|
// done
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3003DF2ETInterface::ResetDevice(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
FT_STATUS ftStatus;
|
||||||
|
int len, i;
|
||||||
|
char rxpacket[100];
|
||||||
|
|
||||||
|
std::cout << "Trying DF2ET-3003 soft reset" << std::endl;
|
||||||
|
|
||||||
|
DWORD n, b;
|
||||||
|
char txpacket[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
char reset_packet[7] = { PKT_HEADER, 0, 3, 0, PKT_RESET, PKT_PARITYBYTE, 3 ^ PKT_RESET ^ PKT_PARITYBYTE };
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for (i = 0; i < 35; i++)
|
||||||
|
{
|
||||||
|
p = &txpacket[0];
|
||||||
|
n = 10;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ftStatus = FT_Write( m_FtdiHandle, p, n, &b);
|
||||||
|
if (FT_OK != ftStatus)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
n -= b;
|
||||||
|
p += b;
|
||||||
|
} while (n > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = &reset_packet[0];
|
||||||
|
n = 7;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ftStatus = FT_Write( m_FtdiHandle, p, n, &b);
|
||||||
|
if (FT_OK != ftStatus)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
n -= b;
|
||||||
|
p += b;
|
||||||
|
} while (n > 0);
|
||||||
|
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
|
||||||
|
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
std::cout << "DF2ET-3003 soft reset succeeded" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "DF2ET-3003 soft reset failed" << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Trying DF2ET-3003 hard reset" << std::endl;
|
||||||
|
|
||||||
|
ftStatus = FT_ClrDtr( m_FtdiHandle );
|
||||||
|
CTimePoint::TaskSleepFor(10);
|
||||||
|
ftStatus = FT_SetDtr( m_FtdiHandle );
|
||||||
|
CTimePoint::TaskSleepFor(10);
|
||||||
|
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
|
||||||
|
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
std::cout << "DF2ET-3003 hard reset succeeded" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "DF2ET-3003 hard reset failed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// cusb3003df2etinterface.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET) on 03/11/2017.
|
||||||
|
// Copyright © 2017 Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cusb3003df2etinterface_h
|
||||||
|
#define cusb3003df2etinterface_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "ftd2xx.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
#include "cusb3003interface.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUsb3003DF2ETInterface : public CUsb3003Interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CUsb3003DF2ETInterface(uint32, uint32, const char *, const char *);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CUsb3003DF2ETInterface() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// low level
|
||||||
|
bool OpenDevice(void);
|
||||||
|
bool ResetDevice(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cusb3003df2etinterface_h */
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// cusb3003hrinterface.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 30/10/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambepacket.h"
|
||||||
|
#include "cusb3003hrinterface.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUsb3003HRInterface::CUsb3003HRInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
|
||||||
|
: CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// low level
|
||||||
|
|
||||||
|
bool CUsb3003HRInterface::ResetDevice(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
FT_STATUS ftStatus;
|
||||||
|
int len;
|
||||||
|
char rxpacket[100];
|
||||||
|
|
||||||
|
//if the device is a USB-3003, it supports reset via UART break signal
|
||||||
|
//printf("reset via uart break...\n");
|
||||||
|
ftStatus = FT_SetBreakOn( m_FtdiHandle );
|
||||||
|
CTimePoint::TaskSleepFor(10);
|
||||||
|
ftStatus = FT_SetBreakOff( m_FtdiHandle );
|
||||||
|
//CTimePoint::TaskSleepFor(10);
|
||||||
|
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
|
||||||
|
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
std::cout << "USB-3003 hard reset failed" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// cusb3003hrinterface.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 30/10/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cusb3003hrinterface_h
|
||||||
|
#define cusb3003hrinterface_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "ftd2xx.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
#include "cusb3003interface.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUsb3003HRInterface : public CUsb3003Interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CUsb3003HRInterface(uint32, uint32, const char *, const char *);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CUsb3003HRInterface() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// low level
|
||||||
|
bool ResetDevice(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cusb3003hrinterface_h */
|
||||||
@ -0,0 +1,324 @@
|
|||||||
|
//
|
||||||
|
// cusb3003interface.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambepacket.h"
|
||||||
|
#include "cusb3003interface.h"
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// configuration:
|
||||||
|
//
|
||||||
|
// PKT_CHANNEL0 = DSTAR (AMBEPLUS)
|
||||||
|
// PKT_CHANNEL1 = DMR/C4FM (AMBE2PLUS)
|
||||||
|
// PKT_CHANNEL2 = UNUSED or HYBRID
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
|
||||||
|
: CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial)
|
||||||
|
{
|
||||||
|
m_uiChCodecs[0]= CODEC_AMBEPLUS;
|
||||||
|
m_uiChCodecs[1]= CODEC_AMBE2PLUS;
|
||||||
|
m_uiChCodecs[2]= CODEC_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CUsb3003Interface::Init(uint8 uiOddCodec)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// init the odd channel
|
||||||
|
m_uiChCodecs[2] = uiOddCodec;
|
||||||
|
|
||||||
|
// base class
|
||||||
|
ok &= CUsb3xxxInterface::Init();
|
||||||
|
|
||||||
|
// do not create our channels now
|
||||||
|
// this is delegated to caller (CVocodecs) as our channel
|
||||||
|
// may be hybrids between 2 interfaces in case of odd n' of channel device)
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage Channels
|
||||||
|
|
||||||
|
uint8 CUsb3003Interface::GetChannelCodec(int iCh) const
|
||||||
|
{
|
||||||
|
uint8 uiCodec = CODEC_NONE;
|
||||||
|
if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) )
|
||||||
|
{
|
||||||
|
uiCodec = m_uiChCodecs[iCh];
|
||||||
|
}
|
||||||
|
return uiCodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage vocodec channels
|
||||||
|
|
||||||
|
CVocodecChannel *CUsb3003Interface::GetChannelWithChannelIn(int iCh)
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel = NULL;
|
||||||
|
bool done = false;
|
||||||
|
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
|
||||||
|
{
|
||||||
|
if ( iCh == 2 )
|
||||||
|
{
|
||||||
|
if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) )
|
||||||
|
{
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
|
||||||
|
{
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh)
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel = NULL;
|
||||||
|
bool done = false;
|
||||||
|
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
|
||||||
|
{
|
||||||
|
if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
|
||||||
|
{
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// decoder helper
|
||||||
|
|
||||||
|
bool CUsb3003Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL };
|
||||||
|
|
||||||
|
if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0))
|
||||||
|
{
|
||||||
|
*ch = buffer.data()[4] - PKT_CHANNEL0;
|
||||||
|
if ( *ch == 0 )
|
||||||
|
packet->SetCodec(CODEC_AMBEPLUS);
|
||||||
|
else if ( *ch == 1 )
|
||||||
|
packet->SetCodec(CODEC_AMBE2PLUS);
|
||||||
|
else
|
||||||
|
packet->SetCodec(CODEC_NONE);
|
||||||
|
packet->SetAmbe(&(buffer.data()[7]));
|
||||||
|
valid = (*ch < GetNbChannels());
|
||||||
|
//std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3003Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if ( (buffer.size() > 6) &&
|
||||||
|
(buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) &&
|
||||||
|
(buffer.data()[5] == PKT_SPEECHD) )
|
||||||
|
{
|
||||||
|
*ch = buffer.data()[4] - PKT_CHANNEL0;
|
||||||
|
packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2);
|
||||||
|
valid = (*ch < GetNbChannels());
|
||||||
|
//std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// encoder helpers
|
||||||
|
|
||||||
|
void CUsb3003Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet)
|
||||||
|
{
|
||||||
|
uint size = (uint16)packet->GetAmbeSize() + 3;
|
||||||
|
buffer->clear();
|
||||||
|
buffer->Append((uint8)PKT_HEADER);
|
||||||
|
buffer->Append((uint8)HIBYTE(size));
|
||||||
|
buffer->Append((uint8)LOBYTE(size));
|
||||||
|
buffer->Append((uint8)PKT_CHANNEL);
|
||||||
|
buffer->Append((uint8)(PKT_CHANNEL0+ch));
|
||||||
|
buffer->Append((uint8)(PKT_CHAND));
|
||||||
|
buffer->Append((uint8)(packet->GetAmbeSize()*8));
|
||||||
|
buffer->Append(packet->GetAmbe(), packet->GetAmbeSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUsb3003Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet)
|
||||||
|
{
|
||||||
|
uint16 size = (uint16)packet->GetVoiceSize() + 3;
|
||||||
|
buffer->clear();
|
||||||
|
buffer->Append((uint8)PKT_HEADER);
|
||||||
|
buffer->Append((uint8)HIBYTE(size));
|
||||||
|
buffer->Append((uint8)LOBYTE(size));
|
||||||
|
buffer->Append((uint8)PKT_SPEECH);
|
||||||
|
buffer->Append((uint8)(PKT_CHANNEL0+ch));
|
||||||
|
buffer->Append((uint8)PKT_SPEECHD);
|
||||||
|
buffer->Append((uint8)(packet->GetVoiceSize()/2));
|
||||||
|
buffer->Append(packet->GetVoice(), packet->GetVoiceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// low level
|
||||||
|
|
||||||
|
bool CUsb3003Interface::OpenDevice(void)
|
||||||
|
{
|
||||||
|
FT_STATUS ftStatus;
|
||||||
|
int baudrate = 921600;
|
||||||
|
|
||||||
|
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted.
|
||||||
|
ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
|
||||||
|
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_OpenEx((PVOID)m_szDeviceName, FT_OPEN_BY_DESCRIPTION, &m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
|
||||||
|
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
|
||||||
|
CTimePoint::TaskSleepFor(50);
|
||||||
|
|
||||||
|
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
|
||||||
|
if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetRts (m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; }
|
||||||
|
|
||||||
|
//for usb-3012 pull DTR high to take AMBE3003 out of reset.
|
||||||
|
//for other devices noting is connected to DTR so it is a dont care
|
||||||
|
ftStatus = FT_ClrDtr(m_FtdiHandle);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
|
||||||
|
|
||||||
|
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
|
||||||
|
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
|
||||||
|
|
||||||
|
// done
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3003Interface::ResetDevice(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int len;
|
||||||
|
char rxpacket[100];
|
||||||
|
char zeropacket[10] =
|
||||||
|
{
|
||||||
|
0,0,0,0,0,0,0,0,0,0
|
||||||
|
};
|
||||||
|
char txpacket[7] =
|
||||||
|
{
|
||||||
|
PKT_HEADER,
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
PKT_RESET,
|
||||||
|
PKT_PARITYBYTE,
|
||||||
|
3 ^ PKT_RESET ^ PKT_PARITYBYTE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet.
|
||||||
|
//first send 350 zeros in case, the chip's receive state is still waiting for characters
|
||||||
|
//if we send more than needed, the exta characters will just get discarded since they do not match the header byte
|
||||||
|
//after that we send PKT_RESET to reset the device
|
||||||
|
//As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it.
|
||||||
|
|
||||||
|
for ( int i = 0; i < 35 ; i++ )
|
||||||
|
{
|
||||||
|
FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// write soft-reset packet
|
||||||
|
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
|
||||||
|
{
|
||||||
|
// read reply
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
|
||||||
|
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
std::cout << "USB-3003 soft reset failed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3003Interface::ConfigureDevice(void)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 };
|
||||||
|
uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 };
|
||||||
|
|
||||||
|
// configure each channels for desired codec
|
||||||
|
for ( int i = 0; i < USB3003_NB_CH; i++ )
|
||||||
|
{
|
||||||
|
switch ( m_uiChCodecs[i] )
|
||||||
|
{
|
||||||
|
case CODEC_AMBEPLUS:
|
||||||
|
ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0);
|
||||||
|
break;
|
||||||
|
case CODEC_AMBE2PLUS:
|
||||||
|
ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0);
|
||||||
|
break;
|
||||||
|
case CODEC_NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// cusb3003interface.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cusb3003interface_h
|
||||||
|
#define cusb3003interface_h
|
||||||
|
|
||||||
|
#include "ftd2xx.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
#include "cusb3xxxinterface.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define USB3003_NB_CH 3
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUsb3003Interface : public CUsb3xxxInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CUsb3003Interface(uint32, uint32, const char *, const char *);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CUsb3003Interface() {}
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(uint8);
|
||||||
|
|
||||||
|
// manage channels
|
||||||
|
int GetNbChannels(void) const { return USB3003_NB_CH; }
|
||||||
|
uint8 GetChannelCodec(int) const;
|
||||||
|
|
||||||
|
// manage vocodec channels
|
||||||
|
CVocodecChannel *GetChannelWithChannelIn(int);
|
||||||
|
CVocodecChannel *GetChannelWithChannelOut(int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// decoder helper
|
||||||
|
bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *);
|
||||||
|
bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *);
|
||||||
|
|
||||||
|
// encoder helpers
|
||||||
|
void EncodeChannelPacket(CBuffer *, int, CAmbePacket *);
|
||||||
|
void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *);
|
||||||
|
|
||||||
|
// low level
|
||||||
|
bool OpenDevice(void);
|
||||||
|
bool ResetDevice(void);
|
||||||
|
bool ConfigureDevice(void);
|
||||||
|
int GetDeviceFifoSize(void) const { return 2; }
|
||||||
|
|
||||||
|
// data
|
||||||
|
uint8 m_uiChCodecs[USB3003_NB_CH];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cusb3003interface_h */
|
||||||
@ -0,0 +1,529 @@
|
|||||||
|
//
|
||||||
|
// cusb3xxxinterface.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cusb3xxxinterface.h"
|
||||||
|
#include "cvocodecchannel.h"
|
||||||
|
#include "cambeserver.h"
|
||||||
|
|
||||||
|
// queues ID
|
||||||
|
#define QUEUE_CHANNEL 0
|
||||||
|
#define QUEUE_SPEECH 1
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
|
||||||
|
{
|
||||||
|
m_FtdiHandle = NULL;
|
||||||
|
m_uiVid = uiVid;
|
||||||
|
m_uiPid = uiPid;
|
||||||
|
::strcpy(m_szDeviceName, szDeviceName);
|
||||||
|
::strcpy(m_szDeviceSerial, szDeviceSerial);
|
||||||
|
m_iSpeechFifolLevel = 0;
|
||||||
|
m_iChannelFifolLevel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CUsb3xxxInterface::~CUsb3xxxInterface()
|
||||||
|
{
|
||||||
|
// delete m_SpeechQueues
|
||||||
|
for ( int i = 0; i < m_SpeechQueues.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_SpeechQueues[i];
|
||||||
|
}
|
||||||
|
m_SpeechQueues.clear();
|
||||||
|
|
||||||
|
// delete m_ChannelQueues
|
||||||
|
for ( int i = 0; i < m_ChannelQueues.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_ChannelQueues[i];
|
||||||
|
}
|
||||||
|
m_ChannelQueues.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::Init(void)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// open USB device
|
||||||
|
std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl;
|
||||||
|
if ( ok &= OpenDevice() )
|
||||||
|
{
|
||||||
|
// reset
|
||||||
|
//std::cout << "Reseting " << m_szDeviceName << "device" << std::endl;
|
||||||
|
if ( ok &= ResetDevice() )
|
||||||
|
{
|
||||||
|
// read version
|
||||||
|
//std::cout << "Reading " << m_szDeviceName << " device version" << std::endl;
|
||||||
|
if ( ok &= ReadDeviceVersion() )
|
||||||
|
{
|
||||||
|
// send configuration packet(s)
|
||||||
|
//std::cout << "Configuring " << m_szDeviceName << " device" << std::endl;
|
||||||
|
ok &= DisableParity();
|
||||||
|
ok &= ConfigureDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// create our queues
|
||||||
|
for ( int i = 0; i < GetNbChannels(); i++ )
|
||||||
|
{
|
||||||
|
m_SpeechQueues.push_back(new CPacketQueue);
|
||||||
|
m_ChannelQueues.push_back(new CPacketQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// base class
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
ok &= CVocodecInterface::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// task
|
||||||
|
|
||||||
|
void CUsb3xxxInterface::Task(void)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
int iCh;
|
||||||
|
CPacketQueue *Queue;
|
||||||
|
CVocodecChannel *Channel;
|
||||||
|
CAmbePacket AmbePacket;
|
||||||
|
CVoicePacket VoicePacket;
|
||||||
|
bool done;
|
||||||
|
|
||||||
|
// TODO :
|
||||||
|
// preserve packets PIDs, so the transcoded CAmbePacket returned
|
||||||
|
// to CStream client is garantied to have the same PID
|
||||||
|
// than the corresponding incoming packet
|
||||||
|
|
||||||
|
// process the device incoming packet
|
||||||
|
// get all packets from device and push them
|
||||||
|
// to the relevant clients queues
|
||||||
|
if ( ReadBuffer(&Buffer) )
|
||||||
|
{
|
||||||
|
if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) )
|
||||||
|
{
|
||||||
|
// update fifo level
|
||||||
|
// as we get a speech packet, it means that the device
|
||||||
|
// channel fifo input decreased by 1
|
||||||
|
m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1);
|
||||||
|
|
||||||
|
// push back to relevant channel voice queue
|
||||||
|
// our incoming channel packet has now been through the decoder
|
||||||
|
// find the coupled channel encoder and push to it's queue
|
||||||
|
// this is were the DVSI enc-dec channel crossover take place
|
||||||
|
Channel = GetChannelWithChannelIn(iCh);
|
||||||
|
if ( Channel != NULL )
|
||||||
|
{
|
||||||
|
Queue = Channel->GetVoiceQueue();
|
||||||
|
CVoicePacket *clone = new CVoicePacket(VoicePacket);
|
||||||
|
clone->ApplyGain(Channel->GetSpeechGain());
|
||||||
|
Queue->push(clone);
|
||||||
|
Channel->ReleaseVoiceQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) )
|
||||||
|
{
|
||||||
|
// update fifo level
|
||||||
|
// as we get a channel packet, it means that the device
|
||||||
|
// speech fifo input decreased by 1
|
||||||
|
m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1);
|
||||||
|
|
||||||
|
// push back to relevant channel outcoming queue
|
||||||
|
// we are done with this packet transcoding
|
||||||
|
// it's final step
|
||||||
|
Channel = GetChannelWithChannelOut(iCh);
|
||||||
|
if ( Channel != NULL )
|
||||||
|
{
|
||||||
|
Queue = Channel->GetPacketQueueOut();
|
||||||
|
CAmbePacket *clone = new CAmbePacket(AmbePacket);
|
||||||
|
Queue->push(clone);
|
||||||
|
Channel->ReleasePacketQueueOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// process the streams (channels) incoming queue
|
||||||
|
// make sure that packets from different channels
|
||||||
|
// are interlaced so to keep the device fifo busy
|
||||||
|
do
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
for ( int i = 0; i < m_Channels.size(); i++)
|
||||||
|
{
|
||||||
|
// get channel
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
|
||||||
|
// any packet in voice queue ?
|
||||||
|
if ( Channel->IsInterfaceOut(this) )
|
||||||
|
{
|
||||||
|
Queue = Channel->GetVoiceQueue();
|
||||||
|
if ( !Queue->empty() )
|
||||||
|
{
|
||||||
|
// get packet
|
||||||
|
CVoicePacket *Packet = (CVoicePacket *)Queue->front();
|
||||||
|
Queue->pop();
|
||||||
|
// this is second step of transcoding
|
||||||
|
// we just received from hardware a decoded speech packet
|
||||||
|
// post it to relevant channel encoder
|
||||||
|
int i = Channel->GetChannelOut();
|
||||||
|
Packet->SetChannel(i);
|
||||||
|
m_SpeechQueues[i]->push(Packet);
|
||||||
|
// done
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
Channel->ReleaseVoiceQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// any packet in ambe queue for us ?
|
||||||
|
if ( Channel->IsInterfaceIn(this) )
|
||||||
|
{
|
||||||
|
Queue = Channel->GetPacketQueueIn();
|
||||||
|
if ( !Queue->empty() )
|
||||||
|
{
|
||||||
|
// get packet
|
||||||
|
CAmbePacket *Packet = (CAmbePacket *)Queue->front();
|
||||||
|
Queue->pop();
|
||||||
|
// this is first step of transcoding
|
||||||
|
// a fresh new packet to be transcoded is showing up
|
||||||
|
// post it to relevant channel decoder
|
||||||
|
int i = Channel->GetChannelIn();
|
||||||
|
Packet->SetChannel(i);
|
||||||
|
m_ChannelQueues[i]->push(Packet);
|
||||||
|
// done
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
Channel->ReleasePacketQueueIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!done);
|
||||||
|
|
||||||
|
// process device incoming queues (aka to device)
|
||||||
|
// interlace speech and channels packets
|
||||||
|
// and post to final device queue
|
||||||
|
do
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
// loop on all channels
|
||||||
|
for ( int i = 0; i < GetNbChannels(); i++ )
|
||||||
|
{
|
||||||
|
// speech
|
||||||
|
if ( !m_SpeechQueues[i]->empty() )
|
||||||
|
{
|
||||||
|
// get packet
|
||||||
|
CPacket *Packet = m_SpeechQueues[i]->front();
|
||||||
|
m_SpeechQueues[i]->pop();
|
||||||
|
// and push to device queue
|
||||||
|
m_DeviceQueue.push(Packet);
|
||||||
|
// next
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
// ambe
|
||||||
|
if ( !m_ChannelQueues[i]->empty() )
|
||||||
|
{
|
||||||
|
// get packet
|
||||||
|
CPacket *Packet = m_ChannelQueues[i]->front();
|
||||||
|
m_ChannelQueues[i]->pop();
|
||||||
|
// and push to device queue
|
||||||
|
m_DeviceQueue.push(Packet);
|
||||||
|
// done = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (!done);
|
||||||
|
|
||||||
|
// process device queue to feed hardware
|
||||||
|
// make sure that device fifo is fed all the time
|
||||||
|
int fifoSize = GetDeviceFifoSize();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
// if device fifo level is zero (device idle)
|
||||||
|
// wait that at least 3 packets are in incoming
|
||||||
|
// queue before restarting
|
||||||
|
if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= (fifoSize+1)) )
|
||||||
|
{
|
||||||
|
// any packet to send ?
|
||||||
|
if ( m_DeviceQueue.size() > 0 )
|
||||||
|
{
|
||||||
|
// yes, get it
|
||||||
|
CPacket *Packet = m_DeviceQueue.front();
|
||||||
|
if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) )
|
||||||
|
{
|
||||||
|
// encode & post
|
||||||
|
EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet);
|
||||||
|
WriteBuffer(Buffer);
|
||||||
|
// remove from queue
|
||||||
|
m_DeviceQueue.pop();
|
||||||
|
// and delete it
|
||||||
|
delete Packet;
|
||||||
|
// update fifo level
|
||||||
|
m_iSpeechFifolLevel++;
|
||||||
|
// next
|
||||||
|
done = false;
|
||||||
|
#ifdef DEBUG_DUMPFILE
|
||||||
|
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) )
|
||||||
|
{
|
||||||
|
// encode & post
|
||||||
|
EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet);
|
||||||
|
WriteBuffer(Buffer);
|
||||||
|
// remove from queue
|
||||||
|
m_DeviceQueue.pop();
|
||||||
|
// and delete it
|
||||||
|
delete Packet;
|
||||||
|
// update fifo level
|
||||||
|
m_iChannelFifolLevel++;
|
||||||
|
// next
|
||||||
|
done = false;
|
||||||
|
#ifdef DEBUG_DUMPFILE
|
||||||
|
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!done);
|
||||||
|
|
||||||
|
// and wait a bit
|
||||||
|
CTimePoint::TaskSleepFor(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// low level
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::ReadDeviceVersion(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int i, len;
|
||||||
|
char rxpacket[128];
|
||||||
|
char txpacket[8] =
|
||||||
|
{
|
||||||
|
PKT_HEADER,
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
PKT_CONTROL,
|
||||||
|
PKT_PRODID,
|
||||||
|
PKT_VERSTRING,
|
||||||
|
PKT_PARITYBYTE,
|
||||||
|
4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE
|
||||||
|
};
|
||||||
|
|
||||||
|
// write packet
|
||||||
|
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
|
||||||
|
{
|
||||||
|
// read reply
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
|
||||||
|
ok = (len != 0);
|
||||||
|
//we succeed in reading a packet, print it out
|
||||||
|
std::cout << "ReadDeviceVersion : ";
|
||||||
|
for ( i = 4; i < len+4 ; i++ )
|
||||||
|
{
|
||||||
|
std::cout << (char)(rxpacket[i] & 0x00ff);
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::DisableParity(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int len;
|
||||||
|
char rxpacket[16];
|
||||||
|
char txpacket[8] =
|
||||||
|
{
|
||||||
|
PKT_HEADER,
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
PKT_CONTROL,
|
||||||
|
PKT_PARITYMODE,0x00,
|
||||||
|
PKT_PARITYBYTE,
|
||||||
|
4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE
|
||||||
|
};
|
||||||
|
|
||||||
|
// write packet
|
||||||
|
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
|
||||||
|
{
|
||||||
|
// read reply
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
|
||||||
|
ok = ((len == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) );
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, int in_gain, int out_gain)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int len;
|
||||||
|
char rxpacket[64];
|
||||||
|
char txpacket[] =
|
||||||
|
{
|
||||||
|
PKT_HEADER,
|
||||||
|
0,
|
||||||
|
33,
|
||||||
|
PKT_CONTROL,
|
||||||
|
0x00,
|
||||||
|
PKT_ECMODE, 0x00,0x00,
|
||||||
|
PKT_DCMODE, 0x00,0x00,
|
||||||
|
PKT_COMPAND,0x00,
|
||||||
|
PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
PKT_CHANFMT,0x00,0x00,
|
||||||
|
PKT_SPCHFMT,0x00,0x00,
|
||||||
|
PKT_GAIN, 0x00,0x00,
|
||||||
|
PKT_INIT, 0x03
|
||||||
|
};
|
||||||
|
|
||||||
|
// update packet content
|
||||||
|
txpacket[4] = pkt_ch;
|
||||||
|
:: memcpy(&(txpacket[14]), pkt_ratep, 12);
|
||||||
|
txpacket[33] = (uint8)(signed char)in_gain;
|
||||||
|
txpacket[34] = (uint8)(signed char)out_gain;
|
||||||
|
|
||||||
|
// write packet
|
||||||
|
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
|
||||||
|
{
|
||||||
|
// read reply
|
||||||
|
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
|
||||||
|
ok = ((len == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) );
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// io level
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::ReadBuffer(CBuffer *buffer)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// any byte in tx queue ?
|
||||||
|
if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK )
|
||||||
|
{
|
||||||
|
//if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) )
|
||||||
|
if ( n != 0 )
|
||||||
|
{
|
||||||
|
buffer->clear();
|
||||||
|
buffer->resize(USB3XXX_MAXPACKETSIZE);
|
||||||
|
n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE);
|
||||||
|
buffer->resize(n);
|
||||||
|
ok = (n != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::WriteBuffer(const CBuffer &buffer)
|
||||||
|
{
|
||||||
|
return FTDI_write_packet(m_FtdiHandle, (const char *)buffer.data(), (int)buffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen)
|
||||||
|
{
|
||||||
|
int plen;
|
||||||
|
|
||||||
|
// first read 4 bytes header
|
||||||
|
if ( FTDI_read_bytes(ftHandle, pkt, 4) )
|
||||||
|
{
|
||||||
|
// get payload length
|
||||||
|
plen = (pkt[1] & 0x00ff);
|
||||||
|
plen <<= 8;
|
||||||
|
plen += (pkt[2] & 0x00ff);
|
||||||
|
// check buffer length
|
||||||
|
if (plen+4 > maxlen)
|
||||||
|
{
|
||||||
|
std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl;
|
||||||
|
FT_Purge(ftHandle, FT_PURGE_RX);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// and get payload
|
||||||
|
if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) )
|
||||||
|
{
|
||||||
|
return plen+4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::FTDI_read_bytes(FT_HANDLE ftHandle, char *buffer, int len)
|
||||||
|
{
|
||||||
|
// this relies on FT_SetTimouts() mechanism
|
||||||
|
int n;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len);
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
//FT_Purge(ftHandle, FT_PURGE_RX);
|
||||||
|
std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, int len)
|
||||||
|
{
|
||||||
|
FT_STATUS ftStatus;
|
||||||
|
bool ok = true;
|
||||||
|
int nwritten;
|
||||||
|
|
||||||
|
if ( len > 0 )
|
||||||
|
{
|
||||||
|
ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten);
|
||||||
|
ok = (ftStatus == FT_OK) && (len == nwritten);
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
FTDI_Error((char *)"FT_Write", ftStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// error reporting
|
||||||
|
|
||||||
|
void CUsb3xxxInterface::FTDI_Error(char *func_string, FT_STATUS ftStatus)
|
||||||
|
{
|
||||||
|
std::cout << "FTDI function " << func_string << " error " << (int)ftStatus << std::endl;
|
||||||
|
}
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
//
|
||||||
|
// cusb3xxxinterface.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cusb3xxxinterface_h
|
||||||
|
#define cusb3xxxinterface_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "ftd2xx.h"
|
||||||
|
#include "cftdidevicedescr.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
#include "cambepacket.h"
|
||||||
|
#include "cvoicepacket.h"
|
||||||
|
#include "cvocodecinterface.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define USB3XXX_MAXPACKETSIZE 1024 // must be multiple of 64
|
||||||
|
|
||||||
|
#define PKT_HEADER 0x61
|
||||||
|
|
||||||
|
#define PKT_CONTROL 0x00
|
||||||
|
#define PKT_CHANNEL 0x01
|
||||||
|
#define PKT_SPEECH 0x02
|
||||||
|
|
||||||
|
#define PKT_SPEECHD 0x00
|
||||||
|
#define PKT_CHAND 0x01
|
||||||
|
#define PKT_RATET 0x09
|
||||||
|
#define PKT_INIT 0x0b
|
||||||
|
#define PKT_PRODID 0x30
|
||||||
|
#define PKT_VERSTRING 0x31
|
||||||
|
#define PKT_PARITYBYTE 0x2F
|
||||||
|
#define PKT_RESET 0x33
|
||||||
|
#define PKT_READY 0x39
|
||||||
|
#define PKT_CHANNEL0 0x40
|
||||||
|
#define PKT_CHANNEL1 0x41
|
||||||
|
#define PKT_CHANNEL2 0x42
|
||||||
|
#define PKT_PARITYMODE 0x3F
|
||||||
|
#define PKT_ECMODE 0x05
|
||||||
|
#define PKT_DCMODE 0x06
|
||||||
|
#define PKT_COMPAND 0x32
|
||||||
|
#define PKT_RATEP 0x0A
|
||||||
|
#define PKT_CHANFMT 0x15
|
||||||
|
#define PKT_SPCHFMT 0x16
|
||||||
|
#define PKT_GAIN 0x4B
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUsb3xxxInterface : public CVocodecInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CUsb3xxxInterface(uint32, uint32, const char *, const char *);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CUsb3xxxInterface();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(void);
|
||||||
|
|
||||||
|
// get
|
||||||
|
const char *GetName(void) const { return m_szDeviceName; }
|
||||||
|
const char *GetSerial(void) const { return m_szDeviceSerial; }
|
||||||
|
|
||||||
|
// task
|
||||||
|
void Task(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// decoder helper
|
||||||
|
virtual bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *) { return false; }
|
||||||
|
virtual bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *) { return false; }
|
||||||
|
|
||||||
|
// encoder helpers
|
||||||
|
virtual void EncodeChannelPacket(CBuffer *, int, CAmbePacket *) {}
|
||||||
|
virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {}
|
||||||
|
|
||||||
|
// low level
|
||||||
|
virtual bool OpenDevice(void) { return false; }
|
||||||
|
virtual bool ResetDevice(void) { return false; }
|
||||||
|
bool ReadDeviceVersion(void);
|
||||||
|
bool DisableParity(void);
|
||||||
|
virtual bool ConfigureDevice(void) { return false; }
|
||||||
|
bool ConfigureChannel(uint8, const uint8 *, int, int);
|
||||||
|
virtual int GetDeviceFifoSize(void) const { return 1; }
|
||||||
|
|
||||||
|
// io level
|
||||||
|
bool ReadBuffer(CBuffer *);
|
||||||
|
bool WriteBuffer(const CBuffer &);
|
||||||
|
int FTDI_read_packet(FT_HANDLE, char *, int);
|
||||||
|
bool FTDI_read_bytes(FT_HANDLE, char *, int);
|
||||||
|
bool FTDI_write_packet(FT_HANDLE, const char *, int);
|
||||||
|
|
||||||
|
// error reporting
|
||||||
|
void FTDI_Error(char *, FT_STATUS);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
uint32 m_uiVid;
|
||||||
|
uint32 m_uiPid;
|
||||||
|
char m_szDeviceName[FTDI_MAX_STRINGLENGTH];
|
||||||
|
char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH];
|
||||||
|
FT_HANDLE m_FtdiHandle;
|
||||||
|
|
||||||
|
// queue
|
||||||
|
std::vector<CPacketQueue*> m_SpeechQueues;
|
||||||
|
std::vector<CPacketQueue*> m_ChannelQueues;
|
||||||
|
CPacketQueue m_DeviceQueue;
|
||||||
|
int m_iSpeechFifolLevel;
|
||||||
|
int m_iChannelFifolLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cusb3xxxinterface_h */
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
//
|
||||||
|
// cvocodecchannel.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cvocodecchannel.h"
|
||||||
|
#include "cvocodecinterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVocodecInterface *InterfaceOut, int iChOut, int iSpeechGain)
|
||||||
|
{
|
||||||
|
m_bOpen = false;
|
||||||
|
m_InterfaceIn = InterfaceIn;
|
||||||
|
m_iChannelIn = iChIn;
|
||||||
|
m_InterfaceOut = InterfaceOut;
|
||||||
|
m_iChannelOut = iChOut;
|
||||||
|
m_iSpeechGain = iSpeechGain;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CVocodecChannel::~CVocodecChannel()
|
||||||
|
{
|
||||||
|
PurgeAllQueues();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// open & close
|
||||||
|
|
||||||
|
bool CVocodecChannel::Open(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
if ( !m_bOpen )
|
||||||
|
{
|
||||||
|
m_bOpen = true;
|
||||||
|
ok = true;
|
||||||
|
PurgeAllQueues();
|
||||||
|
std::cout << "Vocodec channel " <<
|
||||||
|
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
|
||||||
|
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVocodecChannel::Close(void)
|
||||||
|
{
|
||||||
|
if ( m_bOpen )
|
||||||
|
{
|
||||||
|
m_bOpen = false;
|
||||||
|
PurgeAllQueues();
|
||||||
|
std::cout << "Vocodec channel " <<
|
||||||
|
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
|
||||||
|
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// get
|
||||||
|
|
||||||
|
uint8 CVocodecChannel::GetCodecIn(void) const
|
||||||
|
{
|
||||||
|
return m_InterfaceIn->GetChannelCodec(m_iChannelIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CVocodecChannel::GetCodecOut(void) const
|
||||||
|
{
|
||||||
|
return m_InterfaceOut->GetChannelCodec(m_iChannelOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// queues helpers
|
||||||
|
|
||||||
|
void CVocodecChannel::PurgeAllQueues(void)
|
||||||
|
{
|
||||||
|
GetPacketQueueIn()->Purge();
|
||||||
|
ReleasePacketQueueIn();
|
||||||
|
GetPacketQueueOut()->Purge();
|
||||||
|
ReleasePacketQueueOut();
|
||||||
|
GetVoiceQueue()->Purge();
|
||||||
|
ReleaseVoiceQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// cvocodecchannel.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef cvocodecchannel_h
|
||||||
|
#define cvocodecchannel_h
|
||||||
|
|
||||||
|
#include "cpacketqueue.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CVocodecInterface;
|
||||||
|
|
||||||
|
class CVocodecChannel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CVocodecChannel();
|
||||||
|
|
||||||
|
// open & close
|
||||||
|
bool Open(void);
|
||||||
|
bool IsOpen(void) const { return m_bOpen; }
|
||||||
|
void Close(void);
|
||||||
|
|
||||||
|
// get
|
||||||
|
uint8 GetCodecIn(void) const;
|
||||||
|
uint8 GetCodecOut(void) const;
|
||||||
|
int GetChannelIn(void) const { return m_iChannelIn; }
|
||||||
|
int GetChannelOut(void) const { return m_iChannelOut; }
|
||||||
|
int GetSpeechGain(void) const { return m_iSpeechGain; }
|
||||||
|
|
||||||
|
// interfaces
|
||||||
|
bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); }
|
||||||
|
bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); }
|
||||||
|
|
||||||
|
// queues
|
||||||
|
CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; }
|
||||||
|
void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); }
|
||||||
|
CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; }
|
||||||
|
void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); }
|
||||||
|
CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; }
|
||||||
|
void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); }
|
||||||
|
|
||||||
|
// operators
|
||||||
|
//virtual bool operator ==(const CVocodecChannel &) const { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// queues helpers
|
||||||
|
void PurgeAllQueues(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// status
|
||||||
|
bool m_bOpen;
|
||||||
|
|
||||||
|
// connected interfaces
|
||||||
|
CVocodecInterface *m_InterfaceIn;
|
||||||
|
int m_iChannelIn;
|
||||||
|
CVocodecInterface *m_InterfaceOut;
|
||||||
|
int m_iChannelOut;
|
||||||
|
|
||||||
|
// ambe queues
|
||||||
|
CPacketQueue m_QueuePacketIn;
|
||||||
|
CPacketQueue m_QueuePacketOut;
|
||||||
|
// voice queue
|
||||||
|
CPacketQueue m_QueueVoice;
|
||||||
|
|
||||||
|
// settings
|
||||||
|
int m_iSpeechGain;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cvocodecchannel_h */
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
//
|
||||||
|
// cvocodecinterface.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cpacketqueue.h"
|
||||||
|
#include "cvocodecinterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CVocodecInterface::CVocodecInterface()
|
||||||
|
{
|
||||||
|
m_Channels.reserve(5);
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CVocodecInterface::~CVocodecInterface()
|
||||||
|
{
|
||||||
|
// empty channel array
|
||||||
|
// chennels are deleted by their owner (CVocodecs)
|
||||||
|
m_Channels.clear();
|
||||||
|
|
||||||
|
// stop thread
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CVocodecInterface::Init(void)
|
||||||
|
{
|
||||||
|
// reset stop flag
|
||||||
|
m_bStopThread = false;
|
||||||
|
|
||||||
|
// start thread;
|
||||||
|
m_pThread = new std::thread(CVocodecInterface::Thread, this);
|
||||||
|
|
||||||
|
// done
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CVocodecInterface::Thread(CVocodecInterface *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThread )
|
||||||
|
{
|
||||||
|
This->Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage Channels
|
||||||
|
|
||||||
|
void CVocodecInterface::AddChannel(CVocodecChannel *Channel)
|
||||||
|
{
|
||||||
|
m_Channels.push_back(Channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// cvocodecinterface.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cvocodecinterface_h
|
||||||
|
#define cvocodecinterface_h
|
||||||
|
|
||||||
|
#include "cvocodecchannel.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CVocodecs;
|
||||||
|
|
||||||
|
class CVocodecInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CVocodecInterface();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CVocodecInterface();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
virtual bool Init(void);
|
||||||
|
|
||||||
|
// get
|
||||||
|
virtual const char *GetName(void) const { return ""; }
|
||||||
|
|
||||||
|
// manage channels
|
||||||
|
virtual int GetNbChannels(void) const { return 0; }
|
||||||
|
virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; }
|
||||||
|
void AddChannel(CVocodecChannel *);
|
||||||
|
virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; }
|
||||||
|
virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; }
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void Thread(CVocodecInterface *);
|
||||||
|
virtual void Task(void) {};
|
||||||
|
|
||||||
|
// operators
|
||||||
|
virtual bool operator ==(const CVocodecInterface &) const { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// array of channels
|
||||||
|
std::vector<CVocodecChannel *> m_Channels;
|
||||||
|
|
||||||
|
// thread
|
||||||
|
bool m_bStopThread;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cvocodecinterface_h */
|
||||||
@ -0,0 +1,262 @@
|
|||||||
|
//
|
||||||
|
// cvocodecs.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cvocodecs.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// global object
|
||||||
|
|
||||||
|
CVocodecs g_Vocodecs;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CVocodecs::CVocodecs()
|
||||||
|
{
|
||||||
|
m_Interfaces.reserve(5);
|
||||||
|
m_Channels.reserve(20);
|
||||||
|
m_FtdiDeviceDescrs.reserve(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CVocodecs::~CVocodecs()
|
||||||
|
{
|
||||||
|
// delete channels
|
||||||
|
m_MutexChannels.lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < m_Channels.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_Channels[i];
|
||||||
|
}
|
||||||
|
m_Channels.clear();
|
||||||
|
}
|
||||||
|
m_MutexChannels.unlock();
|
||||||
|
|
||||||
|
// delete interfaces
|
||||||
|
m_MutexInterfaces.lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < m_Interfaces.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_Interfaces[i];
|
||||||
|
}
|
||||||
|
m_Interfaces.clear();
|
||||||
|
}
|
||||||
|
m_MutexInterfaces.unlock();
|
||||||
|
|
||||||
|
// delete ftdi device descriptors
|
||||||
|
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_FtdiDeviceDescrs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CVocodecs::Init(void)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
int iNbCh = 0;
|
||||||
|
|
||||||
|
// discover and add vocodecs interfaces
|
||||||
|
DiscoverFtdiDevices();
|
||||||
|
|
||||||
|
// and create interfaces for the discovered devices
|
||||||
|
// first handle all even number of channels devices
|
||||||
|
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
|
||||||
|
{
|
||||||
|
CFtdiDeviceDescr *descr = m_FtdiDeviceDescrs[i];
|
||||||
|
if ( !descr->IsUsed() && IsEven(descr->GetNbChannels()) )
|
||||||
|
{
|
||||||
|
// create the object
|
||||||
|
iNbCh += CFtdiDeviceDescr::CreateInterface(descr, &m_Channels);
|
||||||
|
// and flag as used
|
||||||
|
descr->SetUsed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// next handle all single channel devices.
|
||||||
|
// they must be handeled in pair, or in pair with another
|
||||||
|
// even number of channels device.
|
||||||
|
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
|
||||||
|
{
|
||||||
|
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
|
||||||
|
CFtdiDeviceDescr *descr2 = NULL;
|
||||||
|
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 1) )
|
||||||
|
{
|
||||||
|
// any other single channel device to pair with ?
|
||||||
|
bool found = false;
|
||||||
|
int j = i+1;
|
||||||
|
while ( !found && (j < m_FtdiDeviceDescrs.size()) )
|
||||||
|
{
|
||||||
|
descr2 = m_FtdiDeviceDescrs[j];
|
||||||
|
found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 1));
|
||||||
|
}
|
||||||
|
// found one ?
|
||||||
|
if ( found )
|
||||||
|
{
|
||||||
|
// yes, create and pairboth interfaces
|
||||||
|
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &m_Channels);
|
||||||
|
// and flag as used
|
||||||
|
descr1->SetUsed(true);
|
||||||
|
descr2->SetUsed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now we should have only remaining the 3 chennels device(s)
|
||||||
|
// and possibly an unique single channel device
|
||||||
|
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
|
||||||
|
{
|
||||||
|
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
|
||||||
|
CFtdiDeviceDescr *descr2 = NULL;
|
||||||
|
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) )
|
||||||
|
{
|
||||||
|
// any other odd channel device to pair with ?
|
||||||
|
// any other single channel device to pair with ?
|
||||||
|
bool found = false;
|
||||||
|
int j = i+1;
|
||||||
|
while ( !found && (j < m_FtdiDeviceDescrs.size()) )
|
||||||
|
{
|
||||||
|
descr2 = m_FtdiDeviceDescrs[j];
|
||||||
|
found = (!descr2->IsUsed() && IsOdd(descr2->GetNbChannels()));
|
||||||
|
}
|
||||||
|
// found one ?
|
||||||
|
if ( found )
|
||||||
|
{
|
||||||
|
// yes, create and pairboth interfaces
|
||||||
|
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &m_Channels);
|
||||||
|
// and flag as used
|
||||||
|
descr1->SetUsed(true);
|
||||||
|
descr2->SetUsed(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no, just create a standalone 3003 interface
|
||||||
|
iNbCh += CFtdiDeviceDescr::CreateInterface(descr1, &m_Channels);
|
||||||
|
// and flag as used
|
||||||
|
descr1->SetUsed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels availables" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl;
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialisation helpers
|
||||||
|
|
||||||
|
bool CVocodecs::DiscoverFtdiDevices(void)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int iNbDevices = 0;
|
||||||
|
FT_DEVICE_LIST_INFO_NODE *list;
|
||||||
|
|
||||||
|
// clear vector
|
||||||
|
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_FtdiDeviceDescrs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// and discover
|
||||||
|
if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK )
|
||||||
|
{
|
||||||
|
std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl;
|
||||||
|
ok = true;
|
||||||
|
if ( iNbDevices > 0 )
|
||||||
|
{
|
||||||
|
// allocate the list
|
||||||
|
list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices];
|
||||||
|
|
||||||
|
// fill
|
||||||
|
if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK )
|
||||||
|
{
|
||||||
|
// process
|
||||||
|
for ( int i = 0; i < iNbDevices; i++ )
|
||||||
|
{
|
||||||
|
std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl;
|
||||||
|
CFtdiDeviceDescr *descr = new CFtdiDeviceDescr(
|
||||||
|
LOWORD(list[i].ID), HIWORD(list[i].ID),
|
||||||
|
list[i].Description, list[i].SerialNumber);
|
||||||
|
m_FtdiDeviceDescrs.push_back(descr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and delete
|
||||||
|
delete list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage channels
|
||||||
|
|
||||||
|
CVocodecChannel *CVocodecs::OpenChannel(uint8 uiCodecIn, uint8 uiCodecOut)
|
||||||
|
{
|
||||||
|
CVocodecChannel *Channel = NULL;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
// loop on all interface until suitable & available channel found
|
||||||
|
m_MutexChannels.lock();
|
||||||
|
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
|
||||||
|
{
|
||||||
|
if ( !m_Channels[i]->IsOpen() &&
|
||||||
|
(m_Channels[i]->GetCodecIn() == uiCodecIn) &&
|
||||||
|
(m_Channels[i]->GetCodecOut() == uiCodecOut) )
|
||||||
|
{
|
||||||
|
if ( m_Channels[i]->Open() )
|
||||||
|
{
|
||||||
|
Channel = m_Channels[i];
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_MutexChannels.unlock();
|
||||||
|
|
||||||
|
// done
|
||||||
|
return Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVocodecs::CloseChannel(CVocodecChannel *Channel)
|
||||||
|
{
|
||||||
|
Channel->Close();
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// cvocodecs.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cvocodecs_h
|
||||||
|
#define cvocodecs_h
|
||||||
|
|
||||||
|
#include "cftdidevicedescr.h"
|
||||||
|
#include "cvocodecinterface.h"
|
||||||
|
#include "cvocodecchannel.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CVocodecs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CVocodecs();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CVocodecs();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(void);
|
||||||
|
|
||||||
|
// manage interfaces
|
||||||
|
int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); }
|
||||||
|
CVocodecInterface *GetInterface(int);
|
||||||
|
|
||||||
|
// manage channels
|
||||||
|
CVocodecChannel *OpenChannel(uint8, uint8);
|
||||||
|
void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); }
|
||||||
|
void CloseChannel(CVocodecChannel *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// initialisation helpers
|
||||||
|
bool DiscoverFtdiDevices(void);
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool IsEven(int i) const { return ((i % 2) == 0); }
|
||||||
|
bool IsOdd(int i) const { return !IsEven(i); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// array of interfaces
|
||||||
|
std::mutex m_MutexInterfaces;
|
||||||
|
std::vector<CVocodecInterface *> m_Interfaces;
|
||||||
|
|
||||||
|
// array of channels
|
||||||
|
std::mutex m_MutexChannels;
|
||||||
|
std::vector<CVocodecChannel *> m_Channels;
|
||||||
|
|
||||||
|
// array of FTDI desciptors
|
||||||
|
std::vector<CFtdiDeviceDescr *> m_FtdiDeviceDescrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cvocodecs_h */
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// cvoicepacket.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "cvoicepacket.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CVoicePacket::CVoicePacket()
|
||||||
|
{
|
||||||
|
m_iSize = 0;
|
||||||
|
::memset(m_uiVoice, 0, sizeof(m_uiVoice));
|
||||||
|
}
|
||||||
|
|
||||||
|
CVoicePacket::CVoicePacket(const uint8 *voice, int size)
|
||||||
|
{
|
||||||
|
m_iSize = MIN(size, sizeof(m_uiVoice));
|
||||||
|
::memset(m_uiVoice, 0, sizeof(m_uiVoice));
|
||||||
|
::memcpy(m_uiVoice, voice, m_iSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVoicePacket::CVoicePacket(const CVoicePacket &packet)
|
||||||
|
: CPacket(packet)
|
||||||
|
{
|
||||||
|
m_iSize = packet.m_iSize;
|
||||||
|
::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CVoicePacket::~CVoicePacket()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Set
|
||||||
|
|
||||||
|
void CVoicePacket::SetVoice(const uint8 *voice, int size)
|
||||||
|
{
|
||||||
|
m_iSize = MIN(size, sizeof(m_uiVoice));
|
||||||
|
::memset(m_uiVoice, 0, sizeof(m_uiVoice));
|
||||||
|
::memcpy(m_uiVoice, voice, m_iSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// gain
|
||||||
|
|
||||||
|
void CVoicePacket::ApplyGain(int dB)
|
||||||
|
{
|
||||||
|
float mult = pow(10, dB/20.0);
|
||||||
|
for ( int i = 0; i < m_iSize; i += 2 )
|
||||||
|
{
|
||||||
|
float smp = (float)(short)MAKEWORD(m_uiVoice[i+1], m_uiVoice[i]);
|
||||||
|
smp *= mult;
|
||||||
|
m_uiVoice[i] = HIBYTE((short)smp);
|
||||||
|
m_uiVoice[i+1] = LOBYTE((short)smp);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// cvoicepacket.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cvoicepacket_h
|
||||||
|
#define cvoicepacket_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "cpacket.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
// frame sizes
|
||||||
|
#define VOICE_SIZEMAX 512
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CVoicePacket : public CPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CVoicePacket();
|
||||||
|
CVoicePacket(const uint8 *, int);
|
||||||
|
CVoicePacket(const CVoicePacket &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CVoicePacket();
|
||||||
|
|
||||||
|
// identity
|
||||||
|
bool IsVoice(void) const { return true; }
|
||||||
|
|
||||||
|
// get
|
||||||
|
uint8 *GetVoice(void) { return m_uiVoice; }
|
||||||
|
int GetVoiceSize(void) const { return m_iSize; }
|
||||||
|
|
||||||
|
// set
|
||||||
|
void SetVoice(const uint8 *, int);
|
||||||
|
|
||||||
|
// gain
|
||||||
|
void ApplyGain(int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
int m_iSize;
|
||||||
|
uint8 m_uiVoice[VOICE_SIZEMAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cvoicepacket_h */
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
//
|
||||||
|
// main.cpp
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambeserver.h"
|
||||||
|
|
||||||
|
#include "syslog.h"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// global objects
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// function declaration
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, const char * argv[])
|
||||||
|
{
|
||||||
|
#ifdef RUN_AS_DAEMON
|
||||||
|
|
||||||
|
// redirect cout, cerr and clog to syslog
|
||||||
|
syslog::redirect cout_redir(std::cout);
|
||||||
|
syslog::redirect cerr_redir(std::cerr);
|
||||||
|
syslog::redirect clog_redir(std::clog);
|
||||||
|
|
||||||
|
//Fork the Parent Process
|
||||||
|
pid_t pid, sid;
|
||||||
|
pid = ::fork();
|
||||||
|
//pid = ::vfork();
|
||||||
|
if ( pid < 0 )
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got a good pid, Close the Parent Process
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change File Mask
|
||||||
|
::umask(0);
|
||||||
|
|
||||||
|
//Create a new Signature Id for our child
|
||||||
|
sid = ::setsid();
|
||||||
|
if (sid < 0)
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change Directory
|
||||||
|
// If we cant find the directory we exit with failure.
|
||||||
|
if ( (::chdir("/")) < 0)
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close Standard File Descriptors
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check arguments
|
||||||
|
if ( argc != 2 )
|
||||||
|
{
|
||||||
|
std::cout << "Usage: ambed ip" << std::endl;
|
||||||
|
std::cout << "example: ambed 192.168.178.212" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize ambeserver
|
||||||
|
g_AmbeServer.SetListenIp(CIp(argv[1]));
|
||||||
|
|
||||||
|
// and let it run
|
||||||
|
std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl;
|
||||||
|
if ( !g_AmbeServer.Start() )
|
||||||
|
{
|
||||||
|
std::cout << "Error starting AMBEd" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl;
|
||||||
|
|
||||||
|
#ifdef RUN_AS_DAEMON
|
||||||
|
// run forever
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
// sleep 60 seconds
|
||||||
|
CTimePoint::TaskSleepFor(60000);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// wait any key
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// sleep 60 seconds
|
||||||
|
CTimePoint::TaskSleepFor(60000);
|
||||||
|
//std::cin.get();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// and wait for end
|
||||||
|
g_AmbeServer.Stop();
|
||||||
|
std::cout << "AMBEd stopped" << std::endl;
|
||||||
|
|
||||||
|
// done
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// main.h
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef main_h
|
||||||
|
#define main_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cctype>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// defines
|
||||||
|
|
||||||
|
// version -----------------------------------------------------
|
||||||
|
|
||||||
|
#define VERSION_MAJOR 1
|
||||||
|
#define VERSION_MINOR 3
|
||||||
|
#define VERSION_REVISION 0
|
||||||
|
|
||||||
|
// global ------------------------------------------------------
|
||||||
|
|
||||||
|
//#define RUN_AS_DAEMON
|
||||||
|
#define NB_MAX_STREAMS 99
|
||||||
|
//#define DEBUG_DUMPFILE
|
||||||
|
|
||||||
|
// Transcoder server --------------------------------------------
|
||||||
|
#define TRANSCODER_PORT 10100 // UDP port
|
||||||
|
#define TRANSCODER_KEEPALIVE_PERIOD 5 // in seconds
|
||||||
|
#define TRANSCODER_KEEPALIVE_TIMEOUT 30 // in seconds
|
||||||
|
|
||||||
|
// Codecs -------------------------------------------------------
|
||||||
|
#define CODEC_NONE 0
|
||||||
|
#define CODEC_AMBEPLUS 1
|
||||||
|
#define CODEC_AMBE2PLUS 2
|
||||||
|
|
||||||
|
// Transcoding speech gains
|
||||||
|
#define CODECGAIN_AMBEPLUS -10 // in dB
|
||||||
|
#define CODECGAIN_AMBE2PLUS +10 // in dB
|
||||||
|
|
||||||
|
// Timeouts -----------------------------------------------------
|
||||||
|
#define STREAM_ACTIVITY_TIMEOUT 3 // in seconds
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// typedefs
|
||||||
|
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// macros
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a) < (b))?(a):(b)
|
||||||
|
#define MAX(a,b) ((a) > (b))?(a):(b)
|
||||||
|
#define MAKEWORD(low, high) ((uint16)(((uint8)(low)) | (((uint16)((uint8)(high))) << 8)))
|
||||||
|
#define MAKEDWORD(low, high) ((uint32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16)))
|
||||||
|
#define LOBYTE(w) ((uint8)(uint16)(w & 0x00FF))
|
||||||
|
#define HIBYTE(w) ((uint8)((((uint16)(w)) >> 8) & 0xFF))
|
||||||
|
#define LOWORD(dw) ((uint16)(uint32)(dw & 0x0000FFFF))
|
||||||
|
#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF))
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// global objects
|
||||||
|
|
||||||
|
class CAmbeServer;
|
||||||
|
extern CAmbeServer g_AmbeServer;
|
||||||
|
|
||||||
|
class CVocodecs;
|
||||||
|
extern CVocodecs g_Vocodecs;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* main_h */
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
CC=g++
|
||||||
|
CFLAGS=-c -std=c++11 -pthread
|
||||||
|
LDFLAGS=-std=c++11 -pthread
|
||||||
|
SOURCES=$(wildcard *.cpp)
|
||||||
|
OBJECTS=$(SOURCES:.cpp=.o)
|
||||||
|
EXECUTABLE=ambed
|
||||||
|
|
||||||
|
all: $(SOURCES) $(EXECUTABLE)
|
||||||
|
|
||||||
|
$(EXECUTABLE): $(OBJECTS)
|
||||||
|
$(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(EXECUTABLE) *.o
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir -p /ambed
|
||||||
|
cp $(EXECUTABLE) /ambed/
|
||||||
|
cp ./run /ambed/
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
//
|
||||||
|
// readme
|
||||||
|
// ambed
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 09/07/2017.
|
||||||
|
// Copyright © 2017 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of ambed.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
VERSION: 1.3.0
|
||||||
|
|
||||||
|
Hardware compatibility.
|
||||||
|
======================
|
||||||
|
This version of ambed is compatible with:
|
||||||
|
- DF2ET's AMBE3003USB opensource device (https://github.com/phl0/AMBE3003USB)
|
||||||
|
- LX3JL's USB-3006 opensource device (https://github.com/lx3jl/usb-3006)
|
||||||
|
- DVSI's USB-3000 device
|
||||||
|
- DVSI's USB-3003 device
|
||||||
|
- DVSI's USB-3012 device
|
||||||
|
- NWDR's ThumbDV device
|
||||||
|
- NWDR's ThumbDV-3 device
|
||||||
|
|
||||||
|
Available transcoding channels per device:
|
||||||
|
|
||||||
|
device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
3000(pair) 1 1 2
|
||||||
|
3003 1 1 2
|
||||||
|
3003(pair) 3 3 4
|
||||||
|
3003-3000(pair) 2 2 not tested
|
||||||
|
3006 3 3 6
|
||||||
|
3012 6 6 12
|
||||||
|
|
||||||
|
Multiple devices can be used at the same time.
|
||||||
|
You need to use 3000 by pairs or paired with a 3003
|
||||||
|
Do not to use USB hubs as they have proven making
|
||||||
|
system behaviour unreliable.
|
||||||
|
|
||||||
|
Instructions:
|
||||||
|
=============
|
||||||
|
|
||||||
|
1) Installation of FTDI drivers
|
||||||
|
|
||||||
|
Download from FTDI web site the latest D2XX driver package (tested on 1.4.6).
|
||||||
|
Follow FTDI provided documentation for installation and testing of the drivers.
|
||||||
|
|
||||||
|
|
||||||
|
2) installation of g++ compiler
|
||||||
|
|
||||||
|
# apt-get install build-essential
|
||||||
|
# apt-get install g++-4.7
|
||||||
|
|
||||||
|
2) download and compile ambed
|
||||||
|
|
||||||
|
# git clone https://github.com/LX3JL/xlxd.git
|
||||||
|
# cd xlxd/ambed/
|
||||||
|
# make clean
|
||||||
|
# make
|
||||||
|
# make install
|
||||||
|
|
||||||
|
3) configuring ambed startup script
|
||||||
|
|
||||||
|
# nano /ambed/run
|
||||||
|
|
||||||
|
edit following line to match your IP:
|
||||||
|
|
||||||
|
sudo /ambed/ambed 127.0.0.1 &
|
||||||
|
|
||||||
|
if ambed is running on same machine than xlxd, use default 127.0.0.1
|
||||||
|
otherwise use the machine own IP
|
||||||
|
|
||||||
|
|
||||||
|
4) running ambed
|
||||||
|
|
||||||
|
note:
|
||||||
|
Due to specific FTDI driver implementation, ambed must be running
|
||||||
|
with root privilege, and cannot be run as a daemon.
|
||||||
|
So ambed will display the information and error messages in the
|
||||||
|
terminal it has been started from
|
||||||
|
|
||||||
|
plug at least one USB-3xxx USB device
|
||||||
|
|
||||||
|
# cd /ambed
|
||||||
|
# ./run
|
||||||
|
|
||||||
|
|
||||||
|
during initialisation phase, ambed will scan all USB port to discover
|
||||||
|
and configure ans report status of all available USB-3xxx devices
|
||||||
|
|
||||||
|
|
||||||
|
5) stoping ambed
|
||||||
|
|
||||||
|
find PID of ambed process, using for example ps
|
||||||
|
|
||||||
|
# ps ax | grep ambed
|
||||||
|
|
||||||
|
and kill the process
|
||||||
|
|
||||||
|
# kill xxxx
|
||||||
|
|
||||||
|
where xxxx is PID found previously.
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# start ambed server
|
||||||
|
|
||||||
|
sudo rmmod ftdi_sio
|
||||||
|
sudo rmmod usbserial
|
||||||
|
sudo /ambed/ambed 127.0.0.1 &
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
** Copyright (C) 2014 Jan Pedersen <jp@jp-embedded.com>
|
||||||
|
**
|
||||||
|
** 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 3 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __syslog
|
||||||
|
#define __syslog
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <string>
|
||||||
|
namespace csyslog {
|
||||||
|
#include <syslog.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace syslog
|
||||||
|
{
|
||||||
|
struct level {
|
||||||
|
enum pri {
|
||||||
|
emerg = LOG_EMERG, // A panic condition
|
||||||
|
alert = LOG_ALERT, // A condition that should be corrected
|
||||||
|
critical= LOG_CRIT, // Critical condition, e.g, hard device error
|
||||||
|
error = LOG_ERR, // Errors
|
||||||
|
warning = LOG_WARNING, // Warning messages
|
||||||
|
notice = LOG_NOTICE, // Possibly be handled specially
|
||||||
|
info = LOG_INFO, // Informational
|
||||||
|
debug = LOG_DEBUG // For debugging program
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class streambuf : public std::streambuf
|
||||||
|
{
|
||||||
|
std::string _buf;
|
||||||
|
int _level;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
streambuf() : _level(level::debug) { }
|
||||||
|
void level(int level) { _level = level; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int sync()
|
||||||
|
{
|
||||||
|
if (_buf.size()) {
|
||||||
|
csyslog::syslog(_level, "%s", _buf.c_str());
|
||||||
|
_buf.erase();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_type overflow(int_type c)
|
||||||
|
{
|
||||||
|
if(c == traits_type::eof()) sync();
|
||||||
|
else _buf += static_cast<char>(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ostream : public std::ostream
|
||||||
|
{
|
||||||
|
streambuf _logbuf;
|
||||||
|
public:
|
||||||
|
ostream() : std::ostream(&_logbuf) {}
|
||||||
|
ostream& operator<<(const level::pri lev) { _logbuf.level(lev); return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class redirect
|
||||||
|
{
|
||||||
|
ostream dst;
|
||||||
|
std::ostream &src;
|
||||||
|
std::streambuf * const sbuf;
|
||||||
|
|
||||||
|
public:
|
||||||
|
redirect(std::ostream & src) : src(src), sbuf(src.rdbuf(dst.rdbuf())) { dst << (&src == &std::cout ? level::info : level::error); }
|
||||||
|
~redirect() { src.rdbuf(sbuf); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// cambe.cpp
|
||||||
|
// ambedtest
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 16/05/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cambe.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CAmbe::CAmbe()
|
||||||
|
{
|
||||||
|
::memset(m_uiAmbe, 0, sizeof(m_uiAmbe));
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmbe::CAmbe(uint8 *ambe)
|
||||||
|
{
|
||||||
|
::memcpy(m_uiAmbe, ambe, sizeof(m_uiAmbe));
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// cambe.h
|
||||||
|
// ambedtest
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 16/05/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cambe_h
|
||||||
|
#define cambe_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
// frame sizes
|
||||||
|
#define AMBE_SIZE 9
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CAmbe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CAmbe();
|
||||||
|
CAmbe(uint8 *);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CAmbe() {}
|
||||||
|
|
||||||
|
// get
|
||||||
|
const uint8 *GetData(void) const { return m_uiAmbe; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
uint8 m_uiAmbe[AMBE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cambe_h */
|
||||||
@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// cbuffer.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cbuffer.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CBuffer::CBuffer(uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
resize(len);
|
||||||
|
::memcpy(data(), buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// set
|
||||||
|
|
||||||
|
void CBuffer::Set(uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
resize(len);
|
||||||
|
::memcpy(data(), buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Set(const char *sz)
|
||||||
|
{
|
||||||
|
resize(::strlen(sz)+1);
|
||||||
|
::strcpy((char *)data(), sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint8 *buffer, int len)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+len);
|
||||||
|
::memcpy(&(data()[n]), buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint8 ui, int len)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+len);
|
||||||
|
::memset(&(data()[n]), ui, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint8 ui)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+sizeof(uint8));
|
||||||
|
::memcpy(&(data()[n]), &ui, sizeof(uint8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint16 ui)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+sizeof(uint16));
|
||||||
|
::memcpy(&(data()[n]), &ui, sizeof(uint16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(uint32 ui)
|
||||||
|
{
|
||||||
|
int n = (int)size();
|
||||||
|
resize(n+sizeof(uint32));
|
||||||
|
::memcpy(&(data()[n]), &ui, sizeof(uint32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::Append(const char *sz)
|
||||||
|
{
|
||||||
|
Append((uint8 *)sz, (int)strlen(sz));
|
||||||
|
Append((uint8)0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, uint8 ui)
|
||||||
|
{
|
||||||
|
if ( size() < (i+sizeof(uint8)) )
|
||||||
|
{
|
||||||
|
resize(i+sizeof(uint8));
|
||||||
|
}
|
||||||
|
*(uint8 *)(&(data()[i])) = ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, uint16 ui)
|
||||||
|
{
|
||||||
|
if ( size() < (i+sizeof(uint16)) )
|
||||||
|
{
|
||||||
|
resize(i+sizeof(uint16));
|
||||||
|
}
|
||||||
|
*(uint16 *)(&(data()[i])) = ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, uint32 ui)
|
||||||
|
{
|
||||||
|
if ( size() < (i+sizeof(uint32)) )
|
||||||
|
{
|
||||||
|
resize(i+sizeof(uint32));
|
||||||
|
}
|
||||||
|
*(uint32 *)(&(data()[i])) = ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBuffer::ReplaceAt(int i, const uint8 *ptr, int len)
|
||||||
|
{
|
||||||
|
if ( size() < (i+len) )
|
||||||
|
{
|
||||||
|
resize(i+len);
|
||||||
|
}
|
||||||
|
::memcpy(&(data()[i]), ptr, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operation
|
||||||
|
|
||||||
|
int CBuffer::Compare(uint8 *buffer, int len) const
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
if ( size() >= len )
|
||||||
|
{
|
||||||
|
result = ::memcmp(data(), buffer, len);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CBuffer::Compare(uint8 *buffer, int off, int len) const
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
if ( size() >= (off+len) )
|
||||||
|
{
|
||||||
|
result = ::memcmp(&(data()[off]), buffer, len);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operator
|
||||||
|
|
||||||
|
bool CBuffer::operator ==(const CBuffer &Buffer) const
|
||||||
|
{
|
||||||
|
if ( size() == Buffer.size() )
|
||||||
|
{
|
||||||
|
return (::memcmp((const char *)data(), (const char *)Buffer.data(), size()) == 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBuffer::operator ==(const char *sz) const
|
||||||
|
{
|
||||||
|
if ( size() == ::strlen(sz) )
|
||||||
|
{
|
||||||
|
return (::memcmp((const char *)data(), sz, size()) == 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBuffer::operator const char *() const
|
||||||
|
{
|
||||||
|
return (const char *)data();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// debug
|
||||||
|
|
||||||
|
void CBuffer::DebugDump(std::ofstream &debugout) const
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < size(); i++ )
|
||||||
|
{
|
||||||
|
char sz[16];
|
||||||
|
sprintf(sz, "%02X", data()[i]);
|
||||||
|
debugout << sz;
|
||||||
|
if ( i == size()-1 )
|
||||||
|
{
|
||||||
|
debugout << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugout << ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// cbuffer.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cbuffer_h
|
||||||
|
#define cbuffer_h
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CBuffer : public std::vector<uint8>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CBuffer() {};
|
||||||
|
CBuffer(uint8 *, int);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CBuffer() {};
|
||||||
|
|
||||||
|
// set
|
||||||
|
void Set(uint8 *, int);
|
||||||
|
void Set(const char *);
|
||||||
|
void Append(uint8 *, int);
|
||||||
|
void Append(uint8, int);
|
||||||
|
void Append(uint8);
|
||||||
|
void Append(uint16);
|
||||||
|
void Append(uint32);
|
||||||
|
void Append(const char *);
|
||||||
|
void ReplaceAt(int, uint8);
|
||||||
|
void ReplaceAt(int, uint16);
|
||||||
|
void ReplaceAt(int, uint32);
|
||||||
|
void ReplaceAt(int, const uint8 *, int);
|
||||||
|
|
||||||
|
// operation
|
||||||
|
int Compare(uint8 *, int) const;
|
||||||
|
int Compare(uint8 *, int, int) const;
|
||||||
|
|
||||||
|
// operator
|
||||||
|
bool operator ==(const CBuffer &) const;
|
||||||
|
bool operator ==(const char *) const;
|
||||||
|
operator const char *() const;
|
||||||
|
|
||||||
|
// debug
|
||||||
|
void DebugDump(std::ofstream &) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cbuffer_h */
|
||||||
@ -0,0 +1,305 @@
|
|||||||
|
//
|
||||||
|
// ccodecstream.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "ccodecstream.h"
|
||||||
|
#include "samples.h"
|
||||||
|
#include "ctranscoder.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CCodecStream::CCodecStream(uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut)
|
||||||
|
{
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
m_uiStreamId = uiId;
|
||||||
|
m_uiPid = 0;
|
||||||
|
m_uiCodecIn = uiCodecIn;
|
||||||
|
m_uiCodecOut = uiCodecOut;
|
||||||
|
m_bConnected = false;
|
||||||
|
m_iAmbeSrcPtr = 0;
|
||||||
|
m_iAmbeDestPtr = 0;
|
||||||
|
m_uiNbTotalPacketSent = 0;
|
||||||
|
m_uiNbPacketSent = 0;
|
||||||
|
m_uiNbPacketReceived = 0;
|
||||||
|
m_uiNbPacketBad = 0;
|
||||||
|
m_uiNbPacketTimeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CCodecStream::~CCodecStream()
|
||||||
|
{
|
||||||
|
// close socket
|
||||||
|
m_Socket.Close();
|
||||||
|
|
||||||
|
// kill threads
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CCodecStream::Init(uint16 uiPort)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
// reset stop flag
|
||||||
|
m_bStopThread = false;
|
||||||
|
|
||||||
|
// copy our test data
|
||||||
|
if ( m_uiCodecIn == CODEC_AMBE2PLUS )
|
||||||
|
{
|
||||||
|
// DMR -> DSTAR
|
||||||
|
for ( int i = 0; i < sizeof(g_uiDmrSample); i += AMBE_SIZE )
|
||||||
|
{
|
||||||
|
CAmbe *ambe = new CAmbe(&(g_uiDmrSample[i]));
|
||||||
|
m_AmbeSrc.push_back(ambe);
|
||||||
|
}
|
||||||
|
for ( int i = 0; i < sizeof(g_uiDstarSample); i += AMBE_SIZE )
|
||||||
|
{
|
||||||
|
CAmbe *ambe = new CAmbe(&(g_uiDstarSample[i]));
|
||||||
|
m_AmbeDest.push_back(ambe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// DSTAR -> DMR
|
||||||
|
for ( int i = 0; i < sizeof(g_uiDstarSample); i += AMBE_SIZE )
|
||||||
|
{
|
||||||
|
CAmbe *ambe = new CAmbe(&(g_uiDstarSample[i]));
|
||||||
|
m_AmbeSrc.push_back(ambe);
|
||||||
|
}
|
||||||
|
for ( int i = 0; i < sizeof(g_uiDmrSample); i += AMBE_SIZE )
|
||||||
|
{
|
||||||
|
CAmbe *ambe = new CAmbe(&(g_uiDmrSample[i]));
|
||||||
|
m_AmbeDest.push_back(ambe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create server's IP
|
||||||
|
m_Ip = g_Transcoder.GetAmbedIp();
|
||||||
|
m_uiPort = uiPort;
|
||||||
|
|
||||||
|
// create our socket
|
||||||
|
ok = m_Socket.Open(uiPort);
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
// start thread;
|
||||||
|
m_pThread = new std::thread(CCodecStream::Thread, this);
|
||||||
|
m_bConnected = true;
|
||||||
|
m_FrameTimer.Now();
|
||||||
|
m_uiNbTotalPacketSent = 0;
|
||||||
|
ResetStats();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl;
|
||||||
|
m_bConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCodecStream::Close(void)
|
||||||
|
{
|
||||||
|
// close socket
|
||||||
|
m_bConnected = false;
|
||||||
|
m_Socket.Close();
|
||||||
|
|
||||||
|
// kill threads
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CCodecStream::Thread(CCodecStream *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThread )
|
||||||
|
{
|
||||||
|
This->Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCodecStream::Task(void)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
CIp Ip;
|
||||||
|
uint8 Ambe[AMBE_SIZE];
|
||||||
|
|
||||||
|
// connected ?
|
||||||
|
if ( m_bConnected )
|
||||||
|
{
|
||||||
|
// time to send next packet to be transcoded ?
|
||||||
|
/*if ( m_FrameTimer.DurationSinceNow() >= 0.020 )
|
||||||
|
{
|
||||||
|
// yes
|
||||||
|
m_FrameTimer.Now();
|
||||||
|
|
||||||
|
// encode packet @ send it
|
||||||
|
EncodeAmbePacket(&Buffer, m_AmbeSrc[m_iAmbeSrcPtr]->GetData());
|
||||||
|
m_Socket.Send(Buffer, m_Ip, m_uiPort);
|
||||||
|
|
||||||
|
// and increment pointer
|
||||||
|
m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size();
|
||||||
|
m_uiNbTotalPacketSent++;
|
||||||
|
m_uiNbPacketSent++;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// any packt to send to trancoder ?
|
||||||
|
uint32 uiNbPacketToSend = (uint32)(m_FrameTimer.DurationSinceNow() * 50.0) - m_uiNbTotalPacketSent;
|
||||||
|
if ( uiNbPacketToSend > 0 )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < uiNbPacketToSend; i++ )
|
||||||
|
{
|
||||||
|
// encode packet @ send it
|
||||||
|
EncodeAmbePacket(&Buffer, m_AmbeSrc[m_iAmbeSrcPtr]->GetData());
|
||||||
|
m_Socket.Send(Buffer, m_Ip, m_uiPort);
|
||||||
|
|
||||||
|
// and increment pointer
|
||||||
|
m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size();
|
||||||
|
m_uiNbTotalPacketSent++;
|
||||||
|
m_uiNbPacketSent++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// any packet from transcoder
|
||||||
|
if ( m_Socket.Receive(&Buffer, &Ip, 1) != -1 )
|
||||||
|
{
|
||||||
|
// crack
|
||||||
|
if ( IsValidAmbePacket(Buffer, Ambe) )
|
||||||
|
{
|
||||||
|
m_TimeoutTimer.Now();
|
||||||
|
|
||||||
|
// check the PID
|
||||||
|
// check the transcoded packet
|
||||||
|
/*if ( ::memcmp(Ambe, m_AmbeDest[m_iAmbeDestPtr]->GetData(), AMBE_SIZE) != 0 )
|
||||||
|
{
|
||||||
|
m_uiNbPacketBad++;
|
||||||
|
::memcpy((void *)m_AmbeDest[m_iAmbeDestPtr]->GetData(), Ambe, AMBE_SIZE);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// and increment pointer
|
||||||
|
m_iAmbeDestPtr = (m_iAmbeDestPtr + 1) % m_AmbeDest.size();
|
||||||
|
m_uiNbPacketReceived++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// display stats
|
||||||
|
if ( m_DisplayStatsTimer.DurationSinceNow() >= 2.0 )
|
||||||
|
{
|
||||||
|
m_DisplayStatsTimer.Now();
|
||||||
|
DisplayStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle timeout
|
||||||
|
if ( m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f) )
|
||||||
|
{
|
||||||
|
//std::cout << "ambed packet timeout" << std::endl;
|
||||||
|
m_uiNbPacketTimeout++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// packet decoding helpers
|
||||||
|
|
||||||
|
bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) )
|
||||||
|
{
|
||||||
|
::memcpy(Ambe, &(Buffer.data()[2]), 9);
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// packet encoding helpers
|
||||||
|
|
||||||
|
void CCodecStream::EncodeAmbePacket(CBuffer *Buffer, const uint8 *Ambe)
|
||||||
|
{
|
||||||
|
Buffer->clear();
|
||||||
|
Buffer->Append(m_uiCodecIn);
|
||||||
|
Buffer->Append(m_uiPid);
|
||||||
|
Buffer->Append((uint8 *)Ambe, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// stats helpers
|
||||||
|
|
||||||
|
void CCodecStream::ResetStats(void)
|
||||||
|
{
|
||||||
|
m_StatsTimer.Now();
|
||||||
|
m_DisplayStatsTimer.Now();
|
||||||
|
m_TimeoutTimer.Now();
|
||||||
|
m_uiNbPacketSent = 0;
|
||||||
|
m_uiNbPacketReceived = 0;
|
||||||
|
m_uiNbPacketBad = 0;
|
||||||
|
m_uiNbPacketTimeout = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCodecStream::DisplayStats(void)
|
||||||
|
{
|
||||||
|
// get stats
|
||||||
|
uint32 uiSent = m_uiNbPacketSent;
|
||||||
|
uint32 uiReceived = m_uiNbPacketReceived;
|
||||||
|
uint32 uiBad = m_uiNbPacketBad;
|
||||||
|
double fps = (double)uiReceived / m_StatsTimer.DurationSinceNow();
|
||||||
|
|
||||||
|
// resets
|
||||||
|
ResetStats();
|
||||||
|
|
||||||
|
// displays
|
||||||
|
char sz[256];
|
||||||
|
sprintf(sz, "Stream %d (%d->%d) : %u / %u / %u : %.1f fps",
|
||||||
|
m_uiStreamId, m_uiCodecIn, m_uiCodecOut,
|
||||||
|
uiSent, uiReceived, uiBad, fps);
|
||||||
|
std::cout << sz << std::endl;
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// ccodecstream.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ccodecstream_h
|
||||||
|
#define ccodecstream_h
|
||||||
|
|
||||||
|
#include "csemaphore.h"
|
||||||
|
#include "cudpsocket.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
#include "cambe.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
// frame sizes
|
||||||
|
#define AMBE_SIZE 9
|
||||||
|
#define AMBEPLUS_SIZE 9
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CCodecStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CCodecStream(uint16, uint8, uint8);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CCodecStream();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(uint16);
|
||||||
|
void Close(void);
|
||||||
|
|
||||||
|
// get
|
||||||
|
bool IsConnected(void) const { return m_bConnected; }
|
||||||
|
uint16 GetStreamId(void) const { return m_uiStreamId; }
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void Thread(CCodecStream *);
|
||||||
|
void Task(void);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// packet decoding helpers
|
||||||
|
bool IsValidAmbePacket(const CBuffer &, uint8 *);
|
||||||
|
|
||||||
|
// packet encoding helpers
|
||||||
|
void EncodeAmbePacket(CBuffer *, const uint8 *);
|
||||||
|
|
||||||
|
// stats helpers
|
||||||
|
void ResetStats(void);
|
||||||
|
void DisplayStats(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// test data
|
||||||
|
std::vector<CAmbe *> m_AmbeSrc;
|
||||||
|
int m_iAmbeSrcPtr;
|
||||||
|
std::vector<CAmbe *> m_AmbeDest;
|
||||||
|
int m_iAmbeDestPtr;
|
||||||
|
|
||||||
|
// data
|
||||||
|
uint16 m_uiStreamId;
|
||||||
|
uint16 m_uiPort;
|
||||||
|
uint8 m_uiPid;
|
||||||
|
uint8 m_uiCodecIn;
|
||||||
|
uint8 m_uiCodecOut;
|
||||||
|
|
||||||
|
// socket
|
||||||
|
CIp m_Ip;
|
||||||
|
CUdpSocket m_Socket;
|
||||||
|
bool m_bConnected;
|
||||||
|
|
||||||
|
// thread
|
||||||
|
bool m_bStopThread;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
CTimePoint m_TimeoutTimer;
|
||||||
|
CTimePoint m_FrameTimer;
|
||||||
|
uint32 m_uiNbTotalPacketSent;
|
||||||
|
|
||||||
|
// stats
|
||||||
|
CTimePoint m_StatsTimer;
|
||||||
|
CTimePoint m_DisplayStatsTimer;
|
||||||
|
uint32 m_uiNbPacketSent;
|
||||||
|
uint32 m_uiNbPacketReceived;
|
||||||
|
uint32 m_uiNbPacketBad;
|
||||||
|
uint32 m_uiNbPacketTimeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* ccodecstream_h */
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// cip.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cip.h"
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructors
|
||||||
|
|
||||||
|
CIp::CIp()
|
||||||
|
{
|
||||||
|
::memset(&m_Addr, 0, sizeof(m_Addr));
|
||||||
|
m_Addr.sin_family = AF_INET;
|
||||||
|
}
|
||||||
|
|
||||||
|
CIp::CIp(const char *sz)
|
||||||
|
{
|
||||||
|
::memset(&m_Addr, 0, sizeof(m_Addr));
|
||||||
|
m_Addr.sin_family = AF_INET;
|
||||||
|
// try xxx.xxx.xxx.xxxx first
|
||||||
|
m_Addr.sin_addr.s_addr = inet_addr(sz);
|
||||||
|
if ( m_Addr.sin_addr.s_addr == INADDR_NONE )
|
||||||
|
{
|
||||||
|
// otherwise try to resolve via dns
|
||||||
|
hostent *record = gethostbyname(sz);
|
||||||
|
if( record != NULL )
|
||||||
|
{
|
||||||
|
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CIp::CIp(const struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CIp::CIp(const CIp &ip)
|
||||||
|
{
|
||||||
|
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// set
|
||||||
|
|
||||||
|
void CIp::SetSockAddr(struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operator
|
||||||
|
|
||||||
|
bool CIp::operator ==(const CIp &ip) const
|
||||||
|
{
|
||||||
|
return ( (ip.m_Addr.sin_family == m_Addr.sin_family) &&
|
||||||
|
(ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) &&
|
||||||
|
(ip.m_Addr.sin_port == m_Addr.sin_port)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
CIp::operator const char *() const
|
||||||
|
{
|
||||||
|
return ::inet_ntoa(m_Addr.sin_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// cip.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cip_h
|
||||||
|
#define cip_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CIp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CIp();
|
||||||
|
//CIp(uint8, uint8, uint8, uint8);
|
||||||
|
CIp(const struct sockaddr_in *);
|
||||||
|
CIp(const char *);
|
||||||
|
CIp(const CIp &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CIp() {};
|
||||||
|
|
||||||
|
// sockaddr
|
||||||
|
void SetSockAddr(struct sockaddr_in *);
|
||||||
|
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
|
||||||
|
|
||||||
|
// operator
|
||||||
|
bool operator ==(const CIp &) const;
|
||||||
|
operator const char *() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
struct sockaddr_in m_Addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cip_h */
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// csemaphore.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 16/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "csemaphore.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CSemaphore::CSemaphore()
|
||||||
|
{
|
||||||
|
// Initialized as locked.
|
||||||
|
m_Count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operation
|
||||||
|
|
||||||
|
void CSemaphore::Reset(void)
|
||||||
|
{
|
||||||
|
std::unique_lock<decltype(m_Mutex)> lock(m_Mutex);
|
||||||
|
m_Count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSemaphore::Notify(void)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
m_Count++;
|
||||||
|
m_Condition.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSemaphore::Wait(void)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
m_Condition.wait(lock, [&]{ return m_Count > 0; });
|
||||||
|
m_Count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSemaphore::WaitFor(uint ms)
|
||||||
|
{
|
||||||
|
std::chrono::milliseconds timespan(ms);
|
||||||
|
std::unique_lock<decltype(m_Mutex)> lock(m_Mutex);
|
||||||
|
auto ok = m_Condition.wait_for(lock, timespan, [&]{ return m_Count > 0; });
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
m_Count--;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// csemaphore.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 16/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef csemaphore_h
|
||||||
|
#define csemaphore_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CSemaphore
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CSemaphore();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CSemaphore() {};
|
||||||
|
|
||||||
|
// operation
|
||||||
|
void Reset(void);
|
||||||
|
void Notify(void);
|
||||||
|
void Wait(void);
|
||||||
|
bool WaitFor(uint);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
std::condition_variable m_Condition;
|
||||||
|
size_t m_Count;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* csemaphore_h */
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// ctimepoint.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctimepoint.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CTimePoint::CTimePoint()
|
||||||
|
{
|
||||||
|
m_TimePoint = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operation
|
||||||
|
|
||||||
|
double CTimePoint::DurationSinceNow(void) const
|
||||||
|
{
|
||||||
|
std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now();
|
||||||
|
std::chrono::steady_clock::duration time_span = (Now - m_TimePoint);
|
||||||
|
return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// task
|
||||||
|
|
||||||
|
void CTimePoint::TaskSleepFor(uint ms)
|
||||||
|
{
|
||||||
|
std::chrono::milliseconds timespan(ms);
|
||||||
|
std::this_thread::sleep_for(timespan);
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// ctimepoint.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ctimepoint_h
|
||||||
|
#define ctimepoint_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CTimePoint : public std::chrono::steady_clock::time_point
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CTimePoint();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CTimePoint() {}
|
||||||
|
|
||||||
|
// operation
|
||||||
|
void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); }
|
||||||
|
double DurationSinceNow(void) const;
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void TaskSleepFor(uint);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
std::chrono::steady_clock::time_point m_TimePoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* ctimepoint_h */
|
||||||
@ -0,0 +1,388 @@
|
|||||||
|
//
|
||||||
|
// ctranscoder.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctranscoder.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
// status
|
||||||
|
#define STATUS_IDLE 0
|
||||||
|
#define STATUS_LOGGED 1
|
||||||
|
|
||||||
|
// timeout
|
||||||
|
#define AMBED_OPENSTREAM_TIMEOUT 200 // in ms
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CTranscoder g_Transcoder;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CTranscoder::CTranscoder()
|
||||||
|
{
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
m_Streams.reserve(12);
|
||||||
|
m_bConnected = false;
|
||||||
|
m_LastKeepaliveTime.Now();
|
||||||
|
m_LastActivityTime.Now();
|
||||||
|
m_bStreamOpened = false;
|
||||||
|
m_StreamidOpenStream = 0;
|
||||||
|
m_PortOpenStream = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CTranscoder::~CTranscoder()
|
||||||
|
{
|
||||||
|
// close all streams
|
||||||
|
m_Mutex.lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < m_Streams.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_Streams[i];
|
||||||
|
}
|
||||||
|
m_Streams.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
m_Mutex.unlock();
|
||||||
|
|
||||||
|
// kill threads
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// initialization
|
||||||
|
|
||||||
|
bool CTranscoder::Init(const CIp &ListenIp, const CIp &AmbedIp)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
// reset stop flag
|
||||||
|
m_bStopThread = false;
|
||||||
|
|
||||||
|
// create server's IP
|
||||||
|
m_ListenIp = ListenIp;
|
||||||
|
m_AmbedIp = AmbedIp;
|
||||||
|
|
||||||
|
// create our socket
|
||||||
|
ok = m_Socket.Open(TRANSCODER_PORT);
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
// start thread;
|
||||||
|
m_pThread = new std::thread(CTranscoder::Thread, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_AmbedIp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranscoder::Close(void)
|
||||||
|
{
|
||||||
|
// close socket
|
||||||
|
m_Socket.Close();
|
||||||
|
|
||||||
|
// close all streams
|
||||||
|
m_Mutex.lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < m_Streams.size(); i++ )
|
||||||
|
{
|
||||||
|
delete m_Streams[i];
|
||||||
|
}
|
||||||
|
m_Streams.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
m_Mutex.unlock();
|
||||||
|
|
||||||
|
// kill threads
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CTranscoder::Thread(CTranscoder *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThread )
|
||||||
|
{
|
||||||
|
This->Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranscoder::Task(void)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
CIp Ip;
|
||||||
|
uint16 StreamId;
|
||||||
|
uint16 Port;
|
||||||
|
|
||||||
|
// anything coming in from codec server ?
|
||||||
|
//if ( (m_Socket.Receive(&Buffer, &Ip, 20) != -1) && (Ip == m_Ip) )
|
||||||
|
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
|
||||||
|
{
|
||||||
|
m_LastActivityTime.Now();
|
||||||
|
|
||||||
|
// crack packet
|
||||||
|
if ( IsValidStreamDescrPacket(Buffer, &StreamId, &Port) )
|
||||||
|
{
|
||||||
|
//std::cout << "Transcoder stream " << (int) StreamId << " descr packet " << std::endl;
|
||||||
|
m_bStreamOpened = true;
|
||||||
|
m_StreamidOpenStream = StreamId;
|
||||||
|
m_PortOpenStream = Port;
|
||||||
|
m_SemaphoreOpenStream.Notify();
|
||||||
|
}
|
||||||
|
else if ( IsValidNoStreamAvailablePacket(Buffer) )
|
||||||
|
{
|
||||||
|
m_bStreamOpened = false;
|
||||||
|
m_SemaphoreOpenStream.Notify();
|
||||||
|
}
|
||||||
|
else if ( IsValidKeepAlivePacket(Buffer) )
|
||||||
|
{
|
||||||
|
if ( !m_bConnected )
|
||||||
|
{
|
||||||
|
std::cout << "Transcoder connected at " << Ip << std::endl;
|
||||||
|
}
|
||||||
|
m_bConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle end of streaming timeout
|
||||||
|
//CheckStreamsTimeout();
|
||||||
|
|
||||||
|
// handle queue from reflector
|
||||||
|
//HandleQueue();
|
||||||
|
|
||||||
|
// keep client alive
|
||||||
|
if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
HandleKeepalives();
|
||||||
|
|
||||||
|
// update time
|
||||||
|
m_LastKeepaliveTime.Now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// manage streams
|
||||||
|
|
||||||
|
CCodecStream *CTranscoder::GetStream(uint8 uiCodecIn)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
|
||||||
|
CCodecStream *stream = NULL;
|
||||||
|
|
||||||
|
// do we need transcoding
|
||||||
|
if ( uiCodecIn != CODEC_NONE )
|
||||||
|
{
|
||||||
|
// are we connected to server
|
||||||
|
if ( m_bConnected )
|
||||||
|
{
|
||||||
|
// yes, post openstream request
|
||||||
|
EncodeOpenstreamPacket(&Buffer, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS);
|
||||||
|
m_Socket.Send(Buffer, m_AmbedIp, TRANSCODER_PORT);
|
||||||
|
|
||||||
|
// wait relpy here
|
||||||
|
if ( m_SemaphoreOpenStream.WaitFor(AMBED_OPENSTREAM_TIMEOUT) )
|
||||||
|
{
|
||||||
|
if ( m_bStreamOpened )
|
||||||
|
{
|
||||||
|
std::cout << "ambed openstream(" << m_StreamidOpenStream << ") ok" << std::endl;
|
||||||
|
|
||||||
|
// create stream object
|
||||||
|
stream = new CCodecStream(m_StreamidOpenStream, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS);
|
||||||
|
|
||||||
|
// init it
|
||||||
|
if ( stream->Init(m_PortOpenStream) )
|
||||||
|
{
|
||||||
|
// and append to list
|
||||||
|
Lock();
|
||||||
|
m_Streams.push_back(stream);
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// send close packet
|
||||||
|
EncodeClosestreamPacket(&Buffer, stream->GetStreamId());
|
||||||
|
m_Socket.Send(Buffer, m_AmbedIp, TRANSCODER_PORT);
|
||||||
|
// and delete
|
||||||
|
delete stream;
|
||||||
|
stream = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "ambed openstream failed (no suitable channel available)" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "ambed openstream timeout" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranscoder::ReleaseStream(CCodecStream *stream)
|
||||||
|
{
|
||||||
|
CBuffer Buffer;
|
||||||
|
|
||||||
|
if ( stream != NULL )
|
||||||
|
{
|
||||||
|
// look for the stream
|
||||||
|
bool found = false;
|
||||||
|
Lock();
|
||||||
|
{
|
||||||
|
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
|
||||||
|
{
|
||||||
|
// compare object pointers
|
||||||
|
if ( (m_Streams[i]) == stream )
|
||||||
|
{
|
||||||
|
// send close packet
|
||||||
|
EncodeClosestreamPacket(&Buffer, m_Streams[i]->GetStreamId());
|
||||||
|
m_Socket.Send(Buffer, m_AmbedIp, TRANSCODER_PORT);
|
||||||
|
|
||||||
|
// and close it
|
||||||
|
m_Streams[i]->Close();
|
||||||
|
delete m_Streams[i];
|
||||||
|
m_Streams.erase(m_Streams.begin()+i);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// keepalive helpers
|
||||||
|
|
||||||
|
void CTranscoder::HandleKeepalives(void)
|
||||||
|
{
|
||||||
|
CBuffer keepalive;
|
||||||
|
|
||||||
|
// send keepalive
|
||||||
|
EncodeKeepAlivePacket(&keepalive);
|
||||||
|
m_Socket.Send(keepalive, m_AmbedIp, TRANSCODER_PORT);
|
||||||
|
|
||||||
|
// check if still with us
|
||||||
|
if ( m_bConnected && (m_LastActivityTime.DurationSinceNow() >= TRANSCODER_KEEPALIVE_TIMEOUT) )
|
||||||
|
{
|
||||||
|
// no, disconnect
|
||||||
|
m_bConnected = false;
|
||||||
|
std::cout << "Transcoder keepalive timeout" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet decoding helpers
|
||||||
|
|
||||||
|
bool CTranscoder::IsValidKeepAlivePacket(const CBuffer &Buffer)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' };
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
|
||||||
|
{
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTranscoder::IsValidStreamDescrPacket(const CBuffer &Buffer, uint16 *Id, uint16 *Port)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','S','T','D' };
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if ( (Buffer.size() == 14) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
|
||||||
|
{
|
||||||
|
*Id = *(uint16 *)(&Buffer.data()[8]);
|
||||||
|
*Port = *(uint16 *)(&Buffer.data()[10]);
|
||||||
|
// uint8 CodecIn = Buffer.data()[12];
|
||||||
|
// uint8 CodecOut = Buffer.data()[13];
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTranscoder::IsValidNoStreamAvailablePacket(const CBuffer&Buffer)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' };
|
||||||
|
|
||||||
|
return ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet encoding helpers
|
||||||
|
|
||||||
|
void CTranscoder::EncodeKeepAlivePacket(CBuffer *Buffer)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
Buffer->Append((uint8 *)(const char *)"XLX000 ", 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranscoder::EncodeOpenstreamPacket(CBuffer *Buffer, uint8 uiCodecIn, uint8 uiCodecOut)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','O','S' };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
Buffer->Append((uint8 *)(const char *)"XLX000 ", 8);
|
||||||
|
Buffer->Append((uint8)uiCodecIn);
|
||||||
|
Buffer->Append((uint8)uiCodecOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTranscoder::EncodeClosestreamPacket(CBuffer *Buffer, uint16 uiStreamId)
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'A','M','B','E','D','C','S' };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
Buffer->Append((uint16)uiStreamId);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
//
|
||||||
|
// ctranscoder.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ctranscoder_h
|
||||||
|
#define ctranscoder_h
|
||||||
|
|
||||||
|
#include "csemaphore.h"
|
||||||
|
#include "ccodecstream.h"
|
||||||
|
#include "cudpsocket.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CTranscoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CTranscoder();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CTranscoder();
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
bool Init(const CIp &, const CIp &);
|
||||||
|
void Close(void);
|
||||||
|
|
||||||
|
// locks
|
||||||
|
void Lock(void) { m_Mutex.lock(); }
|
||||||
|
void Unlock(void) { m_Mutex.unlock(); }
|
||||||
|
|
||||||
|
// get
|
||||||
|
const CIp &GetListenIp(void) const { return m_ListenIp; }
|
||||||
|
const CIp &GetAmbedIp(void) const { return m_AmbedIp; }
|
||||||
|
bool IsAmbedConnected(void) const { return m_bConnected; }
|
||||||
|
|
||||||
|
// manage streams
|
||||||
|
CCodecStream *GetStream(uint8);
|
||||||
|
void ReleaseStream(CCodecStream *);
|
||||||
|
|
||||||
|
// task
|
||||||
|
static void Thread(CTranscoder *);
|
||||||
|
void Task(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// keepalive helpers
|
||||||
|
void HandleKeepalives(void);
|
||||||
|
|
||||||
|
// packet decoding helpers
|
||||||
|
bool IsValidKeepAlivePacket(const CBuffer &);
|
||||||
|
bool IsValidStreamDescrPacket(const CBuffer &, uint16 *, uint16 *);
|
||||||
|
bool IsValidNoStreamAvailablePacket(const CBuffer&);
|
||||||
|
|
||||||
|
// packet encoding helpers
|
||||||
|
void EncodeKeepAlivePacket(CBuffer *);
|
||||||
|
void EncodeOpenstreamPacket(CBuffer *, uint8, uint8);
|
||||||
|
void EncodeClosestreamPacket(CBuffer *, uint16);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// IP's
|
||||||
|
CIp m_ListenIp;
|
||||||
|
CIp m_AmbedIp;
|
||||||
|
|
||||||
|
// streams
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
std::vector<CCodecStream *> m_Streams;
|
||||||
|
|
||||||
|
// sync objects for Openstream
|
||||||
|
CSemaphore m_SemaphoreOpenStream;
|
||||||
|
bool m_bStreamOpened;
|
||||||
|
uint16 m_StreamidOpenStream;
|
||||||
|
uint16 m_PortOpenStream;
|
||||||
|
|
||||||
|
// thread
|
||||||
|
bool m_bStopThread;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
|
||||||
|
// socket
|
||||||
|
CUdpSocket m_Socket;
|
||||||
|
bool m_bConnected;
|
||||||
|
|
||||||
|
// time
|
||||||
|
CTimePoint m_LastKeepaliveTime;
|
||||||
|
CTimePoint m_LastActivityTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* ctranscoder_h */
|
||||||
@ -0,0 +1,173 @@
|
|||||||
|
//
|
||||||
|
// cudpsocket.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "cudpsocket.h"
|
||||||
|
#include "ctranscoder.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CUdpSocket::CUdpSocket()
|
||||||
|
{
|
||||||
|
m_Socket = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// destructor
|
||||||
|
|
||||||
|
CUdpSocket::~CUdpSocket()
|
||||||
|
{
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// open & close
|
||||||
|
|
||||||
|
bool CUdpSocket::Open(uint16 uiPort)
|
||||||
|
{
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
// create socket
|
||||||
|
m_Socket = socket(PF_INET,SOCK_DGRAM,0);
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
// initialize sockaddr struct
|
||||||
|
::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in));
|
||||||
|
m_SocketAddr.sin_family = AF_INET;
|
||||||
|
m_SocketAddr.sin_port = htons(uiPort);
|
||||||
|
m_SocketAddr.sin_addr.s_addr = inet_addr(g_Transcoder.GetListenIp());
|
||||||
|
|
||||||
|
if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 )
|
||||||
|
{
|
||||||
|
fcntl(m_Socket, F_SETFL, O_NONBLOCK);
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(m_Socket);
|
||||||
|
m_Socket = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUdpSocket::Close(void)
|
||||||
|
{
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
close(m_Socket);
|
||||||
|
m_Socket = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// read
|
||||||
|
|
||||||
|
int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
|
||||||
|
{
|
||||||
|
struct sockaddr_in Sin;
|
||||||
|
fd_set FdSet;
|
||||||
|
unsigned int uiFromLen = sizeof(struct sockaddr_in);
|
||||||
|
int iRecvLen = -1;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
// socket valid ?
|
||||||
|
if ( m_Socket != -1 )
|
||||||
|
{
|
||||||
|
// control socket
|
||||||
|
FD_ZERO(&FdSet);
|
||||||
|
FD_SET(m_Socket, &FdSet);
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
select(m_Socket + 1, &FdSet, 0, 0, &tv);
|
||||||
|
|
||||||
|
// allocate buffer
|
||||||
|
Buffer->resize(UDP_BUFFER_LENMAX);
|
||||||
|
|
||||||
|
// read
|
||||||
|
iRecvLen = (int)recvfrom(m_Socket,
|
||||||
|
(void *)Buffer->data(), UDP_BUFFER_LENMAX,
|
||||||
|
0, (struct sockaddr *)&Sin, &uiFromLen);
|
||||||
|
|
||||||
|
// handle
|
||||||
|
if ( iRecvLen != -1 )
|
||||||
|
{
|
||||||
|
// adjust buffer size
|
||||||
|
Buffer->resize(iRecvLen);
|
||||||
|
|
||||||
|
// get IP
|
||||||
|
Ip->SetSockAddr(&Sin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return iRecvLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// write
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer.data(), Buffer.size(),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const char *Buffer, const CIp &Ip)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer, ::strlen(Buffer),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
temp.GetSockAddr()->sin_port = htons(destport);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer.data(), Buffer.size(),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport)
|
||||||
|
{
|
||||||
|
CIp temp(Ip);
|
||||||
|
temp.GetSockAddr()->sin_port = htons(destport);
|
||||||
|
return (int)::sendto(m_Socket,
|
||||||
|
(void *)Buffer, ::strlen(Buffer),
|
||||||
|
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// cudpsocket.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cudpsocket_h
|
||||||
|
#define cudpsocket_h
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
//#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "cip.h"
|
||||||
|
#include "cbuffer.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// define
|
||||||
|
|
||||||
|
#define UDP_BUFFER_LENMAX 1024
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CUdpSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CUdpSocket();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
~CUdpSocket();
|
||||||
|
|
||||||
|
// open & close
|
||||||
|
bool Open(uint16);
|
||||||
|
void Close(void);
|
||||||
|
int GetSocket(void) { return m_Socket; }
|
||||||
|
|
||||||
|
// read
|
||||||
|
int Receive(CBuffer *, CIp *, int);
|
||||||
|
|
||||||
|
// write
|
||||||
|
int Send(const CBuffer &, const CIp &);
|
||||||
|
int Send(const CBuffer &, const CIp &, uint16);
|
||||||
|
int Send(const char *, const CIp &);
|
||||||
|
int Send(const char *, const CIp &, uint16);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
int m_Socket;
|
||||||
|
struct sockaddr_in m_SocketAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cudpsocket_h */
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// main.cpp
|
||||||
|
// ambedtest
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 12/05/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ctranscoder.h"
|
||||||
|
|
||||||
|
#define NB_STREAM 1
|
||||||
|
|
||||||
|
int main(int argc, const char * argv[])
|
||||||
|
{
|
||||||
|
std::vector<CCodecStream *> Streams;
|
||||||
|
|
||||||
|
// check args
|
||||||
|
if ( argc != 5 )
|
||||||
|
{
|
||||||
|
std::cout << "Usage: ambedtest myip ambedip nbdmrstreams nbdstarstreams" << std::endl;
|
||||||
|
std::cout << "example: ambed 192.168.178.212 127.0.0.1 2 2" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init the transcoder
|
||||||
|
std::cout << "Connecting to ambed server " << std::endl;
|
||||||
|
g_Transcoder.Init(CIp(argv[1]), CIp(argv[2]));
|
||||||
|
while ( !g_Transcoder.IsAmbedConnected() );
|
||||||
|
std::cout << "Press enter to start test" << std::endl;
|
||||||
|
std::cin.get();
|
||||||
|
|
||||||
|
// create streams
|
||||||
|
int nDmr = atoi(argv[3]);
|
||||||
|
int nDstar = atoi(argv[4]);
|
||||||
|
|
||||||
|
for ( int i = 0; i < nDmr; i++ )
|
||||||
|
{
|
||||||
|
CTimePoint::TaskSleepFor(300);
|
||||||
|
Streams.push_back(g_Transcoder.GetStream(CODEC_AMBE2PLUS));
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < nDstar; i++ )
|
||||||
|
{
|
||||||
|
CTimePoint::TaskSleepFor(300);
|
||||||
|
Streams.push_back(g_Transcoder.GetStream(CODEC_AMBEPLUS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// and loop wait
|
||||||
|
std::cin.get();
|
||||||
|
|
||||||
|
// close
|
||||||
|
for ( int i = 0; i < Streams.size(); i++ )
|
||||||
|
{
|
||||||
|
g_Transcoder.ReleaseStream(Streams[i]);
|
||||||
|
}
|
||||||
|
g_Transcoder.Close();
|
||||||
|
|
||||||
|
// done
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// main.h
|
||||||
|
// ambedtest
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef main_h
|
||||||
|
#define main_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cctype>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// defines
|
||||||
|
|
||||||
|
// version -----------------------------------------------------
|
||||||
|
|
||||||
|
#define VERSION_MAJOR 1
|
||||||
|
#define VERSION_MINOR 0
|
||||||
|
#define VERSION_REVISION 0
|
||||||
|
|
||||||
|
// global ------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Transcoder server --------------------------------------------
|
||||||
|
|
||||||
|
#define TRANSCODER_PORT 10100 // UDP port
|
||||||
|
#define TRANSCODER_KEEPALIVE_PERIOD 5 // in seconds
|
||||||
|
#define TRANSCODER_KEEPALIVE_TIMEOUT 30 // in seconds
|
||||||
|
#define TRANSCODER_AMBEPACKET_TIMEOUT 400 // in ms
|
||||||
|
|
||||||
|
// codec --------------------------------------------------------
|
||||||
|
|
||||||
|
#define CODEC_NONE 0
|
||||||
|
#define CODEC_AMBEPLUS 1 // DStar
|
||||||
|
#define CODEC_AMBE2PLUS 2 // DMR
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// system constants ---------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// typedefs
|
||||||
|
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// macros
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a) < (b))?(a):(b)
|
||||||
|
#define MAX(a,b) ((a) > (b))?(a):(b)
|
||||||
|
#define MAKEWORD(low, high) ((uint16)(((uint8)(low)) | (((uint16)((uint8)(high))) << 8)))
|
||||||
|
#define MAKEDWORD(low, high) ((uint32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16)))
|
||||||
|
#define LOBYTE(w) ((uint8)(uint16)(w & 0x00FF))
|
||||||
|
#define HIBYTE(w) ((uint8)((((uint16)(w)) >> 8) & 0xFF))
|
||||||
|
#define LOWORD(dw) ((uint16)(uint32)(dw & 0x0000FFFF))
|
||||||
|
#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF))
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// global objects
|
||||||
|
|
||||||
|
class CTranscoder;
|
||||||
|
extern CTranscoder g_Transcoder;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* main_h */
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
CC=g++
|
||||||
|
CFLAGS=-c -std=c++11 -pthread
|
||||||
|
LDFLAGS=-std=c++11 -pthread
|
||||||
|
SOURCES=$(wildcard *.cpp)
|
||||||
|
OBJECTS=$(SOURCES:.cpp=.o)
|
||||||
|
EXECUTABLE=ambedtest
|
||||||
|
|
||||||
|
all: $(SOURCES) $(EXECUTABLE)
|
||||||
|
|
||||||
|
$(EXECUTABLE): $(OBJECTS)
|
||||||
|
$(CC) $(LDFLAGS) $(OBJECTS) -Wl,-rpath,/usr/local/lib -o $@
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(EXECUTABLE) *.o
|
||||||
@ -0,0 +1,359 @@
|
|||||||
|
//
|
||||||
|
// dmrtodstarsample.h
|
||||||
|
// ambedtest
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 16/05/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef dmrtodstarsample_h
|
||||||
|
#define dmrtodstarsample_h
|
||||||
|
|
||||||
|
uint8 g_uiDmrSample[] =
|
||||||
|
{
|
||||||
|
0xFD,0xAF,0xA2,0x32,0x0D,0x69,0x75,0xEF,0x64,
|
||||||
|
0xDF,0x8F,0x80,0x10,0x2F,0x4D,0x61,0xEE,0x44,
|
||||||
|
0xDF,0x8F,0x80,0x10,0x2F,0x4D,0x61,0xEF,0x20,
|
||||||
|
0xFD,0x8D,0xA2,0x10,0x2C,0x6D,0x42,0x8F,0x44,
|
||||||
|
0xBD,0xED,0xD7,0x74,0x2A,0x05,0x96,0x8F,0x88,
|
||||||
|
0xBD,0xED,0xD7,0x74,0x2A,0x05,0xA5,0xAF,0x20,
|
||||||
|
0xBD,0xED,0xD7,0x74,0x2A,0x04,0xA5,0xBE,0x88,
|
||||||
|
0xFD,0x8D,0xA2,0x10,0x2C,0x6D,0x61,0xAE,0x44,
|
||||||
|
0xBD,0xED,0xD7,0x74,0x2A,0x05,0xA5,0xAE,0x20,
|
||||||
|
0xAD,0xED,0xC6,0x74,0x2A,0x05,0xA5,0xAE,0x88,
|
||||||
|
0xBF,0xCD,0xA7,0x72,0x41,0xFF,0x30,0x23,0xA6,
|
||||||
|
0x8C,0xFD,0x84,0x50,0x63,0xDB,0x16,0x02,0x20,
|
||||||
|
0xFF,0x8F,0xC3,0x72,0x44,0xA1,0xD7,0x42,0x08,
|
||||||
|
0xCA,0xB9,0xE7,0x54,0x44,0x69,0xF1,0x3C,0xD2,
|
||||||
|
0xC8,0xB9,0xD6,0x54,0x64,0x08,0xC2,0x4A,0x20,
|
||||||
|
0xC8,0xB9,0xC6,0x54,0x65,0x0A,0xF1,0x4A,0xE2,
|
||||||
|
0x8A,0xF9,0x83,0x72,0x01,0x06,0x45,0x2A,0x6F,
|
||||||
|
0x9B,0xE9,0x83,0x72,0x00,0x04,0x45,0x2B,0x20,
|
||||||
|
0xB9,0xE9,0xA1,0x54,0x61,0x06,0x01,0x2B,0x6E,
|
||||||
|
0xBB,0xE9,0x83,0x50,0x01,0x22,0x21,0x0B,0x6E,
|
||||||
|
0xBB,0xE9,0x83,0x50,0x01,0x20,0x00,0x2B,0x20,
|
||||||
|
0xBB,0xE9,0x93,0x50,0x00,0x22,0x01,0x2B,0x6E,
|
||||||
|
0xB9,0xE9,0xA1,0x54,0x60,0x06,0x01,0x2B,0x6E,
|
||||||
|
0x99,0xE9,0x83,0x74,0x41,0x37,0x00,0x2B,0x20,
|
||||||
|
0x99,0xEB,0x83,0x52,0x45,0x57,0x15,0x2B,0x6A,
|
||||||
|
0x99,0xEB,0x83,0x52,0x45,0x57,0x14,0x2B,0x6A,
|
||||||
|
0x99,0xEA,0x83,0x52,0x45,0x57,0x14,0x29,0x20,
|
||||||
|
0x99,0xEA,0x83,0x52,0x45,0x57,0x14,0x2B,0x7B,
|
||||||
|
0xFB,0xAB,0xC4,0x76,0x42,0x0C,0xD1,0x2E,0xE2,
|
||||||
|
0x91,0xD2,0xE2,0xE5,0x03,0x16,0x1A,0xD5,0x1C,
|
||||||
|
0x6C,0x15,0xAD,0x96,0x64,0x55,0xC9,0xD3,0xA7,
|
||||||
|
0xFD,0xAE,0xC0,0x30,0x66,0xD2,0xD1,0x76,0x09,
|
||||||
|
0xD0,0x52,0xE5,0x16,0xEF,0xDF,0xA3,0x5F,0x20,
|
||||||
|
0xE6,0x8E,0x2D,0xA8,0xEF,0x80,0x33,0x82,0x9B,
|
||||||
|
0xD3,0xAA,0x1B,0xDC,0x8D,0x48,0x33,0x9E,0x72,
|
||||||
|
0xA4,0x0A,0x00,0x21,0x8D,0x55,0xF8,0x22,0x20,
|
||||||
|
0xA6,0x1A,0x23,0x64,0x9B,0x55,0xCB,0x13,0xF7,
|
||||||
|
0xC2,0x36,0x20,0x77,0xEF,0x34,0xB4,0xB8,0x46,
|
||||||
|
0x82,0x47,0x24,0x67,0xC7,0x90,0xE4,0x70,0x20,
|
||||||
|
0x78,0xFA,0x0D,0x11,0x4A,0x44,0xE5,0x2B,0xAA,
|
||||||
|
0x08,0xDF,0x2A,0x5E,0x34,0xF9,0x54,0x19,0x9F,
|
||||||
|
0xDF,0x2E,0x2E,0xE9,0x78,0x38,0x09,0xEB,0x20,
|
||||||
|
0xBC,0x7D,0x29,0xAB,0x72,0xA9,0x1A,0x05,0x55,
|
||||||
|
0xC1,0xBE,0xE3,0x77,0x22,0xEC,0x0C,0xD3,0x90,
|
||||||
|
0xC7,0xE3,0xA7,0x17,0x15,0xF0,0x81,0x3C,0x84,
|
||||||
|
0xF4,0x40,0xC2,0x73,0x32,0xBB,0xBF,0x80,0x0F,
|
||||||
|
0x4E,0xFF,0xA5,0x46,0x45,0x44,0xDB,0x7F,0x41,
|
||||||
|
0x2C,0xAE,0xE0,0x61,0x60,0x28,0x0E,0x3B,0x1C,
|
||||||
|
0xB7,0xC1,0x95,0xD4,0xA6,0x9F,0xE3,0xC1,0x01,
|
||||||
|
0x26,0x61,0xFF,0x84,0x11,0xBC,0x81,0x0F,0x7B,
|
||||||
|
0xD2,0x74,0xC8,0xD2,0x77,0xBB,0x6D,0x1B,0x20,
|
||||||
|
0x95,0x49,0xC7,0x27,0x02,0x40,0xB7,0x00,0x10,
|
||||||
|
0xE4,0xAB,0xE4,0x12,0x15,0x24,0x5D,0xFB,0x2F,
|
||||||
|
0xF3,0x30,0xDC,0x32,0x11,0xDD,0x76,0x8D,0x24,
|
||||||
|
0xE8,0x9A,0xE6,0x76,0x66,0x7B,0x85,0x0B,0xC1,
|
||||||
|
0xEA,0xB8,0xC6,0x54,0x60,0x6B,0x85,0x0B,0xE3,
|
||||||
|
0xEA,0xB8,0xC6,0x54,0x60,0x7B,0x85,0x09,0x20,
|
||||||
|
0xE9,0xAA,0xC4,0x76,0x61,0x5D,0x94,0x09,0xE7,
|
||||||
|
0xE9,0xAA,0xC4,0x76,0x61,0x5D,0x94,0x09,0xE7,
|
||||||
|
0xBA,0x7C,0x88,0xD7,0xC0,0x97,0x65,0x08,0x20,
|
||||||
|
0x92,0xB2,0x3E,0xCE,0xEC,0xF6,0x49,0x2A,0x69,
|
||||||
|
0xB0,0xF7,0x61,0x04,0x80,0xB9,0xBC,0xC9,0x26,
|
||||||
|
0x94,0xD0,0x44,0x40,0x96,0x22,0x8C,0xE0,0x20,
|
||||||
|
0x96,0xB4,0x61,0xC2,0xB3,0x33,0xF1,0x44,0x10,
|
||||||
|
0xA4,0x93,0x61,0xA0,0x39,0xDE,0xD8,0xA3,0xE7,
|
||||||
|
0x96,0xB0,0x45,0x6E,0x3C,0x90,0x64,0x98,0x20,
|
||||||
|
0x82,0xB6,0x06,0x87,0x30,0xFD,0x3D,0x01,0x46,
|
||||||
|
0xE0,0xA1,0x49,0xD4,0x33,0x4E,0x75,0x65,0xB7,
|
||||||
|
0xE6,0xB5,0x4F,0xD4,0x15,0xF1,0x20,0x4D,0x20,
|
||||||
|
0xD4,0xB6,0x4C,0xF6,0x33,0xE5,0x10,0x19,0x1E,
|
||||||
|
0xE4,0xD7,0x2C,0xDB,0x80,0x89,0x08,0xFF,0x00,
|
||||||
|
0xC7,0xE5,0x4F,0xBD,0x8B,0x52,0xFD,0x25,0x20,
|
||||||
|
0x83,0xE7,0x63,0x35,0x81,0xFA,0xBF,0x8E,0x23,
|
||||||
|
0xE5,0x82,0x21,0x33,0x95,0x5A,0x5B,0x81,0x15,
|
||||||
|
0xA1,0x8D,0x02,0x22,0xA3,0x5A,0x47,0x58,0x20,
|
||||||
|
0xE2,0x8E,0x66,0x68,0x6D,0xF2,0x4F,0x74,0x0B,
|
||||||
|
0x84,0xAF,0x12,0xCA,0x3A,0x50,0xF5,0x9F,0xE3,
|
||||||
|
0xAB,0x6A,0xE6,0x46,0x55,0x38,0x09,0x91,0x1C,
|
||||||
|
0xCC,0x56,0xE4,0x70,0x45,0x1E,0x73,0x39,0x2D,
|
||||||
|
0xDB,0x61,0xA0,0x52,0x4E,0x79,0xA2,0xD9,0xDB,
|
||||||
|
0x84,0x95,0xCE,0xE2,0x89,0xEB,0xCB,0x2E,0x1C,
|
||||||
|
0x3F,0x2C,0xDA,0x82,0x7B,0x32,0x11,0xDD,0xF2,
|
||||||
|
0xA6,0xA3,0xE0,0x00,0x67,0xE9,0x54,0x5A,0x71,
|
||||||
|
0x9B,0x21,0xD4,0x16,0x49,0x76,0x40,0xF8,0x20,
|
||||||
|
0xA5,0xB5,0x7A,0xBD,0xF4,0xC5,0x9D,0xBF,0xEB,
|
||||||
|
0xA5,0xCE,0x40,0x86,0xAC,0x3E,0xC8,0x58,0xDD,
|
||||||
|
0x90,0xAC,0x21,0x43,0xC1,0x5A,0x43,0x4F,0x1C,
|
||||||
|
0xC0,0x9E,0x66,0x5A,0x4F,0x86,0x5D,0x71,0x0E,
|
||||||
|
0x81,0x89,0x4E,0xF7,0x25,0xA4,0x08,0xF0,0xCF,
|
||||||
|
0xBB,0x23,0x6C,0xCC,0x22,0x81,0xC1,0xE8,0x20,
|
||||||
|
0x9F,0x4E,0xE0,0x03,0x36,0xD0,0x7A,0x89,0x37,
|
||||||
|
0x88,0xA3,0xC0,0x27,0x66,0xE2,0xDD,0x9C,0xFF,
|
||||||
|
0xB9,0x82,0xC2,0x45,0x04,0xE5,0xCF,0xDF,0x20,
|
||||||
|
0xD2,0x34,0xE2,0xE6,0xBF,0x9D,0xAB,0xA9,0x88,
|
||||||
|
0x97,0x6F,0x1D,0x98,0xAD,0xD2,0xDB,0x5A,0xD6,
|
||||||
|
0xC1,0x4E,0x63,0x32,0x8B,0xD4,0x0B,0x5C,0x20,
|
||||||
|
0xF0,0x7C,0x40,0x07,0xBD,0x97,0x5C,0x2C,0x95,
|
||||||
|
0x94,0x38,0x03,0x04,0xDF,0x74,0x98,0x63,0xF7,
|
||||||
|
0xB4,0x1A,0x41,0x04,0x86,0xFD,0x4C,0xBD,0x84,
|
||||||
|
0x80,0x65,0x27,0x15,0xF5,0xB1,0x94,0x31,0xF7,
|
||||||
|
0xA4,0x43,0x22,0x17,0xD0,0x7B,0xC3,0x59,0x5F,
|
||||||
|
0xC6,0x4C,0x45,0x06,0x05,0xB0,0x31,0xA3,0x20,
|
||||||
|
0xF2,0x2C,0xA6,0x32,0x51,0xE2,0x41,0x48,0x26,
|
||||||
|
0xA3,0x4E,0x1A,0xAC,0x35,0x94,0xA1,0xF5,0xDF,
|
||||||
|
0x92,0x19,0x0F,0x4C,0x65,0xB0,0x9D,0x55,0x20,
|
||||||
|
0x6F,0xD6,0xDE,0x53,0xCF,0xA2,0xF3,0x2F,0x6D,
|
||||||
|
0x8F,0x21,0x8B,0x4A,0xCF,0x6D,0x90,0x61,0xDE,
|
||||||
|
0xB8,0x00,0x5F,0xCA,0x41,0xF4,0xD5,0xDD,0x84,
|
||||||
|
0xF8,0x50,0x4A,0x8A,0x6F,0x54,0x90,0x42,0xD8,
|
||||||
|
0x14,0xED,0xA6,0x1D,0x3D,0x5F,0x90,0x85,0x51,
|
||||||
|
0xB4,0xB2,0xC2,0x35,0x55,0xAD,0x21,0x69,0x24,
|
||||||
|
0xAF,0x86,0xC4,0x31,0x35,0x3C,0xD9,0x84,0x73,
|
||||||
|
0x8F,0xB6,0xC6,0x33,0x75,0x19,0x9A,0xC0,0x02,
|
||||||
|
0x9C,0xA6,0xD5,0x53,0x55,0x7A,0xDC,0x87,0x20,
|
||||||
|
0xF9,0xA9,0xE7,0x70,0x64,0x59,0xA5,0x6B,0xF4,
|
||||||
|
0xF9,0xAB,0xE7,0x56,0x60,0x29,0x93,0x59,0xE6,
|
||||||
|
0xE9,0xA9,0xE7,0x70,0x64,0x4B,0xA4,0x68,0x1C,
|
||||||
|
0xCD,0x9D,0xE2,0x52,0x42,0xA3,0xA0,0x26,0x2C,
|
||||||
|
0xD0,0x25,0x82,0x93,0xB4,0x33,0x2F,0x73,0xF3,
|
||||||
|
0x65,0x1C,0xDD,0x05,0x73,0x26,0xB1,0x09,0x84,
|
||||||
|
0x80,0x95,0xC7,0x67,0x35,0x43,0x14,0x05,0x9D,
|
||||||
|
0xBF,0xEE,0x94,0x52,0x21,0xC9,0x34,0x24,0x92,
|
||||||
|
0xDD,0x8C,0xC1,0x52,0x00,0xA7,0xC3,0x56,0x20,
|
||||||
|
0xDD,0x8C,0xC1,0x52,0x00,0xB5,0xE0,0x76,0x7F,
|
||||||
|
0xFD,0x8C,0xC2,0x50,0x02,0xD6,0xE5,0x74,0x5B,
|
||||||
|
0xFD,0x8C,0xC2,0x50,0x02,0xD4,0xE4,0x76,0x20,
|
||||||
|
0xDD,0xAC,0xE2,0x52,0x06,0x92,0xD3,0x74,0x5B,
|
||||||
|
0xCC,0xBC,0xE2,0x52,0x06,0x92,0xD3,0x77,0x59,
|
||||||
|
0xCC,0xBC,0xE3,0x52,0x07,0x92,0xE0,0x77,0x20,
|
||||||
|
0xAC,0xAA,0x40,0x20,0x00,0x44,0x40,0x80,0x80,
|
||||||
|
0xC6,0xBE,0x1C,0xBA,0xFD,0xB0,0x31,0xB5,0x9B,
|
||||||
|
0xC4,0xBE,0x27,0xB1,0xCB,0x74,0x6B,0x1F,0x04,
|
||||||
|
0xCC,0x24,0x43,0x23,0xC5,0xD4,0xAB,0x96,0xB7,
|
||||||
|
0xDA,0x30,0x64,0x56,0x80,0x4F,0x9F,0xDD,0x0A,
|
||||||
|
0xBB,0x10,0x02,0x1F,0x4C,0xB0,0xF1,0xF4,0x20,
|
||||||
|
0xFA,0x05,0x0F,0x59,0x55,0xFC,0x5F,0x5A,0x5F,
|
||||||
|
0xAF,0x85,0xA6,0x41,0x28,0xA7,0x48,0x0C,0x09,
|
||||||
|
0xF8,0xF2,0xA5,0x15,0x13,0xAC,0x5D,0xBE,0x20,
|
||||||
|
0xEB,0xF0,0xA6,0x11,0x55,0xC9,0x7B,0xD9,0x12,
|
||||||
|
0x9A,0x82,0x82,0x17,0x78,0x09,0x3D,0x00,0xE2,
|
||||||
|
0xFD,0x2C,0x3C,0x89,0x5C,0x6E,0x09,0xCB,0x20,
|
||||||
|
0x9E,0x6D,0x29,0xE9,0x13,0xDA,0x1E,0x73,0x71,
|
||||||
|
0xAE,0x6C,0xC1,0x63,0x50,0xA1,0x5D,0xDF,0x33,
|
||||||
|
0xC6,0xBA,0xE7,0x23,0x02,0x02,0x49,0x8A,0x20,
|
||||||
|
0xB1,0x85,0xC7,0x57,0x41,0x10,0x41,0x50,0xE9,
|
||||||
|
0x5D,0xD5,0xEC,0x53,0xAA,0xD2,0xB3,0x3F,0x7F,
|
||||||
|
0x9A,0x5A,0xA5,0x66,0x59,0xA1,0x8E,0x7B,0x20,
|
||||||
|
0xFA,0x28,0x78,0xBA,0x27,0x7D,0xCD,0x59,0x06,
|
||||||
|
0x8D,0x15,0x4A,0xDF,0x05,0x19,0xF1,0x86,0x95,
|
||||||
|
0x91,0x96,0xE7,0x55,0x24,0x06,0x55,0x04,0x1C,
|
||||||
|
0x85,0x4B,0x34,0xD2,0x06,0xB9,0xDA,0x37,0xFF,
|
||||||
|
0xF5,0x2B,0x62,0xD0,0x05,0xD3,0x5F,0x36,0x21,
|
||||||
|
0xF6,0x3A,0x42,0xC1,0x33,0xD5,0x4A,0x44,0x20,
|
||||||
|
0xD2,0x0F,0x66,0xE1,0x03,0x3B,0x5C,0x4D,0xAA,
|
||||||
|
0xE6,0x6F,0x4B,0xA0,0x43,0x19,0xD1,0x55,0x7E,
|
||||||
|
0xE6,0x7D,0x5A,0xE4,0x67,0x7E,0xF5,0x56,0x20,
|
||||||
|
0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B,
|
||||||
|
0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B,
|
||||||
|
0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x20,
|
||||||
|
0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B,
|
||||||
|
0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8 g_uiDstarSample[] =
|
||||||
|
{
|
||||||
|
0x67,0xE4,0x04,0x42,0x22,0x0F,0xE5,0x95,0xB6,
|
||||||
|
0x5E,0x84,0x1E,0x52,0xC6,0x0D,0x1C,0xD6,0x08,
|
||||||
|
0x6A,0xC5,0x12,0x5A,0x85,0x89,0x10,0x56,0x02,
|
||||||
|
0x72,0xA7,0x16,0x62,0x84,0x03,0x04,0xF6,0x0E,
|
||||||
|
0x1E,0x26,0x1A,0x03,0x43,0x8D,0x68,0xE3,0xB4,
|
||||||
|
0x6E,0xA4,0x9A,0x5A,0xE4,0x0A,0x18,0x74,0x0E,
|
||||||
|
0x02,0xA4,0x14,0x3B,0x03,0x0E,0x40,0xB1,0x32,
|
||||||
|
0x6A,0xE6,0x90,0x62,0xC5,0x8D,0x20,0x94,0x46,
|
||||||
|
0x62,0xC5,0x12,0x7A,0x66,0x08,0x18,0x06,0x8C,
|
||||||
|
0x2E,0xC5,0x12,0x23,0x62,0x02,0x54,0xA1,0xBC,
|
||||||
|
0x7A,0xC4,0x12,0x7A,0x84,0x00,0x08,0xD7,0x42,
|
||||||
|
0x6A,0x84,0x12,0x42,0xC7,0x89,0x00,0x26,0xC4,
|
||||||
|
0x1A,0xC4,0x14,0x23,0xA3,0x85,0x4C,0x20,0x7A,
|
||||||
|
0x0E,0x27,0x90,0x03,0x22,0x09,0x48,0xC2,0xF4,
|
||||||
|
0x3A,0x66,0x92,0x2B,0x21,0x8E,0x6C,0x73,0xF0,
|
||||||
|
0x6A,0xE5,0x14,0x72,0x66,0x04,0x00,0x97,0x42,
|
||||||
|
0x1E,0x47,0x90,0x3B,0x23,0x80,0x70,0x81,0xBC,
|
||||||
|
0x6E,0x86,0x18,0x52,0xC4,0x85,0x24,0x26,0x84,
|
||||||
|
0x46,0xE7,0x16,0x6A,0xE5,0x05,0x0C,0xB6,0xC8,
|
||||||
|
0xAC,0x47,0xBC,0x00,0x45,0x06,0x54,0x27,0x6E,
|
||||||
|
0xC8,0xA7,0x3A,0x79,0x61,0x80,0x0C,0xC2,0x5A,
|
||||||
|
0x76,0xA7,0x1E,0x5A,0x84,0x04,0x20,0xB5,0x0E,
|
||||||
|
0xC8,0x05,0xBC,0x49,0x01,0x83,0x10,0x41,0x56,
|
||||||
|
0xB0,0x26,0x30,0x20,0xE6,0x00,0x40,0x06,0xAE,
|
||||||
|
0x66,0xA7,0x1E,0x4A,0x87,0x05,0x0C,0x26,0x0C,
|
||||||
|
0xD1,0x29,0xAE,0x11,0x02,0x00,0x38,0x05,0x66,
|
||||||
|
0x1E,0xC4,0x12,0x33,0x03,0x05,0x78,0x23,0x72,
|
||||||
|
0x7A,0x47,0x18,0x5A,0x46,0x8C,0x38,0x06,0xC6,
|
||||||
|
0xB8,0x05,0xB4,0x28,0x05,0x02,0x74,0xF6,0xE8,
|
||||||
|
0x02,0xE4,0x12,0x23,0xE0,0x80,0x60,0xF1,0x36,
|
||||||
|
0x12,0x64,0x1C,0x13,0x22,0x0A,0x74,0x32,0xB2,
|
||||||
|
0x2E,0xE6,0x94,0x1B,0x22,0x0B,0x74,0xF2,0xF4,
|
||||||
|
0x5E,0xC7,0x9C,0x5A,0xC4,0x89,0x2C,0x17,0xC4,
|
||||||
|
0x9D,0xE6,0xBC,0xA9,0x85,0xA0,0xFD,0xCD,0xB2,
|
||||||
|
0x8E,0x56,0x02,0x69,0x7F,0x8A,0xF7,0x6A,0x0B,
|
||||||
|
0xE0,0x6B,0x9E,0x13,0xC8,0xFE,0x22,0x45,0xAD,
|
||||||
|
0xA9,0x00,0x8C,0xAA,0xBD,0x78,0x03,0xBB,0x90,
|
||||||
|
0xA8,0xB7,0x7F,0xE6,0xF9,0xA6,0x32,0x28,0xD9,
|
||||||
|
0xF1,0x55,0xFD,0xF5,0xFB,0xAA,0x6B,0x51,0xFA,
|
||||||
|
0xBC,0xF1,0xF1,0x46,0x8A,0x6F,0x7B,0xB7,0x2A,
|
||||||
|
0xED,0x34,0x4D,0xF6,0x4D,0xAC,0x28,0xCF,0xC9,
|
||||||
|
0xA0,0x74,0xC6,0xB0,0x4F,0x83,0x1E,0x39,0xE6,
|
||||||
|
0x9C,0xD4,0x92,0xA1,0x15,0xBC,0xA2,0xB7,0xA1,
|
||||||
|
0xEB,0x90,0x18,0xE0,0x55,0x23,0x96,0x45,0xC3,
|
||||||
|
0xD3,0x10,0xB0,0x92,0x13,0xF4,0xC8,0x52,0x8A,
|
||||||
|
0xD0,0x4B,0x8C,0x63,0x00,0x28,0xF1,0x66,0x27,
|
||||||
|
0x5A,0xA6,0x12,0x03,0x47,0x66,0x7B,0x89,0x42,
|
||||||
|
0x5F,0xC3,0x90,0x1A,0x35,0xC6,0xB3,0x8F,0x62,
|
||||||
|
0x52,0xC7,0x92,0x4A,0xF7,0x47,0x2C,0xD4,0x42,
|
||||||
|
0x3B,0xE2,0x8C,0x2A,0x40,0x12,0xC2,0x62,0xA4,
|
||||||
|
0x6B,0xA2,0x1C,0x43,0xE6,0xEA,0xE0,0xC3,0x2A,
|
||||||
|
0xEA,0x27,0x14,0x9B,0xA5,0xB2,0xD0,0xE9,0xB6,
|
||||||
|
0x4F,0x82,0x90,0x3A,0xE5,0x87,0xBF,0x9E,0xE6,
|
||||||
|
0xBE,0x0F,0x92,0xF2,0x41,0x47,0x75,0x37,0x64,
|
||||||
|
0x56,0x45,0x12,0x52,0x64,0x0A,0x20,0xA6,0xCE,
|
||||||
|
0xA8,0xC9,0x04,0xF9,0x22,0x8A,0x29,0x46,0x97,
|
||||||
|
0x3A,0x07,0x02,0x52,0x01,0x19,0x75,0xC8,0x4A,
|
||||||
|
0x12,0x47,0x14,0x13,0x62,0x88,0x60,0x83,0xF6,
|
||||||
|
0xBD,0xEB,0xA0,0x70,0x26,0x89,0x50,0x23,0x94,
|
||||||
|
0x76,0x45,0x90,0x6A,0x46,0x04,0x2C,0x37,0x8C,
|
||||||
|
0xE8,0xC2,0x18,0x9B,0xC4,0x9F,0x1B,0xAA,0xA6,
|
||||||
|
0x89,0xAC,0x58,0xE1,0xE8,0x97,0x4D,0x9D,0xBF,
|
||||||
|
0xCC,0x7A,0x45,0x9D,0xEF,0x8B,0x8F,0x49,0x1E,
|
||||||
|
0xF8,0x19,0x41,0x95,0xAD,0xC9,0x8B,0x88,0x99,
|
||||||
|
0xFC,0xDF,0x43,0xA4,0x8B,0xD7,0xE0,0x5A,0xB5,
|
||||||
|
0x8C,0xBC,0xCD,0xF1,0x8F,0x5E,0xB8,0xFC,0x85,
|
||||||
|
0xDD,0x5A,0x5D,0x99,0xD8,0x4E,0x4A,0x2A,0xA9,
|
||||||
|
0x88,0x1E,0x4D,0xD6,0x9C,0x8A,0x61,0xDB,0x96,
|
||||||
|
0xB9,0x38,0xED,0x29,0x36,0xE0,0x37,0xFD,0xD8,
|
||||||
|
0x9C,0xBF,0x2C,0x20,0x67,0x8C,0xF3,0x58,0xB1,
|
||||||
|
0xF8,0xBB,0x20,0x78,0xA5,0xD8,0xF0,0xBF,0x21,
|
||||||
|
0xF5,0x18,0xB2,0x09,0x91,0xFA,0x6E,0x02,0x51,
|
||||||
|
0xC8,0x7A,0x2A,0x79,0xFE,0x1D,0x22,0xA4,0x17,
|
||||||
|
0xD1,0x9A,0x65,0x20,0x7B,0x81,0xF2,0x5C,0x51,
|
||||||
|
0xE8,0x79,0x79,0x2F,0x3C,0x54,0xF2,0xBB,0x7A,
|
||||||
|
0xE1,0xDF,0x6D,0x9C,0x3A,0x01,0x93,0xF1,0xE4,
|
||||||
|
0xB9,0x98,0x79,0xBD,0x5A,0xC4,0x81,0xCE,0x09,
|
||||||
|
0x98,0x5E,0xE9,0xA4,0x2A,0xD5,0x3B,0x3D,0x97,
|
||||||
|
0xD5,0x38,0xFF,0x87,0xD7,0xBE,0x99,0xFB,0x90,
|
||||||
|
0x17,0xE3,0x9C,0x53,0x02,0x0B,0xFB,0x1A,0x5E,
|
||||||
|
0x23,0xA3,0x0A,0x32,0x41,0x14,0xFA,0xE3,0xAE,
|
||||||
|
0xF8,0xEB,0xAA,0x71,0x4E,0x1B,0x0E,0xA4,0xD1,
|
||||||
|
0x5E,0x85,0x90,0x4B,0xAE,0x86,0xDE,0x1F,0xF2,
|
||||||
|
0x7B,0xE1,0x04,0x5A,0x0D,0x1B,0x7C,0x9C,0xE2,
|
||||||
|
0x6F,0xA5,0x12,0x62,0x02,0xF1,0xA3,0xC2,0x00,
|
||||||
|
0x6B,0x66,0x06,0x3B,0x90,0x28,0xB6,0x8A,0x32,
|
||||||
|
0xF9,0x19,0xFD,0xC8,0xCF,0x00,0xC5,0xA9,0x74,
|
||||||
|
0xC1,0x1C,0x73,0xC9,0x68,0xD4,0x82,0x5A,0x9B,
|
||||||
|
0xB4,0xDF,0xE7,0x87,0x4A,0x8B,0xEE,0xE9,0x8C,
|
||||||
|
0x9B,0x53,0xD1,0x4C,0x7D,0xDC,0x45,0xEA,0x9F,
|
||||||
|
0x93,0x57,0x0C,0x5B,0xA0,0x61,0x7F,0xD1,0x61,
|
||||||
|
0xE3,0x75,0x1C,0xB0,0x23,0x12,0xAA,0x1B,0xE9,
|
||||||
|
0x6B,0xC4,0x9C,0x0B,0x42,0x98,0xE4,0x7F,0x8A,
|
||||||
|
0x62,0xE2,0x86,0x32,0x92,0x42,0x4E,0x4C,0x92,
|
||||||
|
0x43,0xA4,0x94,0x72,0x42,0xB2,0x9B,0x03,0xCE,
|
||||||
|
0xC3,0x42,0x2A,0x11,0xBE,0x82,0xAF,0x47,0x8A,
|
||||||
|
0x90,0xFE,0x45,0x3D,0x49,0x2C,0xD5,0x2F,0xD2,
|
||||||
|
0xA8,0x5D,0x4D,0x3D,0x38,0xE9,0xC1,0x2F,0x9E,
|
||||||
|
0xB1,0x52,0x63,0xF7,0x99,0xFC,0x98,0x69,0x09,
|
||||||
|
0xC8,0x51,0xFB,0xA5,0x0A,0xEA,0xDC,0x8A,0x9D,
|
||||||
|
0xF9,0x16,0x6D,0x9C,0xEB,0xF8,0x4E,0x4A,0x86,
|
||||||
|
0xCC,0x57,0xE9,0x67,0x3B,0xA0,0x6D,0x2B,0x8F,
|
||||||
|
0x81,0xF1,0x6F,0x0F,0xDE,0xC9,0xD1,0x9A,0xDB,
|
||||||
|
0xA0,0x56,0xED,0xBE,0xD0,0xB9,0xED,0xCB,0x92,
|
||||||
|
0x9C,0x55,0xB8,0xD8,0x21,0xFA,0x0D,0xC5,0xF2,
|
||||||
|
0xC4,0xF3,0xEE,0x3A,0x07,0x57,0xAF,0x0F,0x13,
|
||||||
|
0x2F,0x22,0x12,0x3A,0x33,0x68,0xA0,0x46,0x10,
|
||||||
|
0x8D,0xA0,0x2A,0x1B,0x9C,0x05,0xD1,0x6B,0x10,
|
||||||
|
0x1E,0x84,0x0A,0x5B,0xC8,0x5F,0xAB,0x82,0xBE,
|
||||||
|
0xEA,0x03,0x32,0x69,0x32,0xE2,0xEB,0x33,0xC3,
|
||||||
|
0x2F,0xA6,0x1A,0x13,0xE5,0xFE,0xDB,0x24,0xFE,
|
||||||
|
0x73,0xE3,0x1C,0x63,0x16,0xEA,0xEC,0xE2,0xEE,
|
||||||
|
0x6A,0xC4,0x12,0x33,0x95,0x26,0x57,0x28,0x82,
|
||||||
|
0xB9,0x24,0x78,0x51,0xE1,0x15,0xB0,0xCF,0xE1,
|
||||||
|
0xE0,0x85,0x32,0x61,0x23,0x0E,0x00,0x91,0x90,
|
||||||
|
0x5A,0x46,0x12,0x72,0xA4,0x80,0x38,0xF6,0xCE,
|
||||||
|
0xBD,0x8B,0x04,0x9B,0x84,0x07,0x24,0xBB,0x48,
|
||||||
|
0x6E,0x25,0x18,0x52,0xC4,0x02,0x24,0xB4,0x8A,
|
||||||
|
0x92,0x42,0x14,0x91,0x45,0x18,0x71,0x94,0xB4,
|
||||||
|
0xD9,0x6C,0x9E,0x9A,0x86,0x86,0x2A,0x36,0xA0,
|
||||||
|
0xEA,0x8C,0x02,0x02,0xE1,0xEE,0x79,0x7B,0xFB,
|
||||||
|
0x7E,0x65,0x0C,0x13,0x24,0x9A,0x1D,0xBF,0xBE,
|
||||||
|
0x42,0x85,0x18,0x72,0x65,0x0E,0x14,0x05,0xCE,
|
||||||
|
0x5E,0xA5,0x16,0x72,0x45,0x00,0x3C,0x55,0x8A,
|
||||||
|
0xB9,0x0B,0xAA,0x48,0x86,0x8A,0x40,0xE0,0x9C,
|
||||||
|
0xC5,0x49,0xA0,0x31,0x00,0x07,0x00,0xA5,0x6A,
|
||||||
|
0x7E,0xC4,0x10,0x72,0xA4,0x80,0x08,0xC7,0xC2,
|
||||||
|
0x0A,0x47,0x12,0x03,0x81,0x00,0x6C,0xC0,0xFE,
|
||||||
|
0x1A,0xC7,0x9E,0x03,0xE0,0x81,0x68,0xA0,0xB4,
|
||||||
|
0x06,0xC5,0x10,0x33,0x63,0x88,0x60,0x31,0xB6,
|
||||||
|
0x1A,0xE4,0x1A,0x13,0xE1,0x0E,0x4C,0x50,0xB8,
|
||||||
|
0x9A,0xA1,0xC8,0x28,0xE0,0x72,0x0D,0xAE,0xD8,
|
||||||
|
0x92,0x30,0xC9,0x7B,0x5B,0x4F,0x5D,0x6D,0xBE,
|
||||||
|
0xCE,0x94,0xD9,0xC8,0xDF,0x4F,0xAC,0xC8,0x12,
|
||||||
|
0xCB,0x13,0xCF,0xE6,0x4C,0x8C,0xEB,0x6F,0xD7,
|
||||||
|
0xEB,0x17,0xE5,0x10,0x9B,0xD6,0xE8,0xC4,0xAF,
|
||||||
|
0x8B,0xD1,0xAC,0x7B,0xCA,0x5F,0x12,0xA4,0xAF,
|
||||||
|
0x8E,0xD3,0xA2,0x71,0x95,0xF8,0x8E,0x7E,0xCA,
|
||||||
|
0x3B,0x44,0x1C,0x23,0x75,0xFE,0xDF,0xD5,0x7A,
|
||||||
|
0x33,0x43,0x96,0x32,0x30,0xE4,0xB0,0xA6,0x96,
|
||||||
|
0x4F,0xE1,0x18,0x63,0xB6,0x26,0xD8,0xE1,0x6A,
|
||||||
|
0x6F,0xC7,0x16,0x62,0xE3,0xFA,0x97,0x91,0x82,
|
||||||
|
0xF1,0xC7,0x8C,0xFB,0x86,0xE3,0xCE,0x75,0xB2,
|
||||||
|
0xA3,0x92,0x38,0xDB,0x45,0xF8,0x88,0x75,0xBE,
|
||||||
|
0x02,0xE3,0x16,0x5B,0x46,0xBC,0x5C,0x2D,0xDC,
|
||||||
|
0xBE,0xB6,0x80,0xF9,0x03,0x90,0x2B,0x3C,0x26,
|
||||||
|
0xF8,0x2A,0x3C,0x29,0x95,0x42,0xF9,0xA4,0xDE,
|
||||||
|
0xC4,0x42,0x32,0xA3,0x21,0xBA,0xEF,0x07,0xB2,
|
||||||
|
0xE8,0x88,0xBC,0x58,0xC5,0xAB,0xAE,0x8B,0xD6,
|
||||||
|
0x0F,0x00,0x1E,0x63,0x23,0x86,0xCF,0xCB,0x9A,
|
||||||
|
0xBB,0xF1,0x2E,0xD8,0xA7,0x58,0x07,0x86,0xDB,
|
||||||
|
0xFD,0x0A,0x94,0xBB,0xE0,0x15,0x4D,0xD4,0x06,
|
||||||
|
0xE1,0xB7,0xA3,0xDB,0x00,0x43,0x2A,0x5A,0xEB,
|
||||||
|
0xF4,0x99,0x40,0x31,0xD0,0x1D,0x7B,0xDD,0x72,
|
||||||
|
0xA5,0xD4,0x65,0x92,0x84,0xCF,0x7A,0x2F,0xD5,
|
||||||
|
0x89,0x4A,0x80,0x9B,0xF5,0xC6,0x0C,0xAA,0x84,
|
||||||
|
0x88,0x30,0xF8,0xB0,0xB5,0xC5,0x19,0x48,0x1A,
|
||||||
|
0xFC,0xE5,0x3C,0x59,0x41,0x03,0x28,0xF2,0x9C,
|
||||||
|
0x99,0xC9,0x26,0x58,0xE6,0x09,0x6C,0x61,0xD8,
|
||||||
|
0x99,0xE8,0xAA,0x78,0x85,0x0F,0x64,0x32,0x92,
|
||||||
|
0x5E,0xC7,0x18,0x52,0xC4,0x05,0x3C,0xA6,0x8A,
|
||||||
|
0x0E,0xC4,0x94,0x3B,0x22,0x03,0x60,0x60,0x70,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* dmrtodstarsample_h */
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 371 B |
@ -0,0 +1 @@
|
|||||||
|
fr.png
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1 @@
|
|||||||
|
no.png
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 788 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 566 B |
@ -0,0 +1 @@
|
|||||||
|
fr.png
|
||||||
|
After Width: | Height: | Size: 1022 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1 @@
|
|||||||
|
fr.png
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1 @@
|
|||||||
|
au.png
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1 @@
|
|||||||
|
fr.png
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |