📄 main.cxx
字号:
digits = "";
currentMenu = menuNumber;
PString menuName = psprintf("%s%i", MENU_PREFIX, menuNumber);
if (menuNames.GetStringsIndex(menuName) == P_MAX_INDEX)
return FALSE;
PTRACE(1, "Starting menu " << menuNumber);
PConfig menu(menuName);
PString startCmd = menu.GetString("start");
if (!startCmd.IsEmpty())
ProcessMenuCmd(startCmd);
return TRUE;
}
BOOL MyH323Connection::ProcessMenuCmd(const PString & cmdStr)
{
PTRACE(1, "Processing menu cmd " << cmdStr);
PStringArray tokens = cmdStr.Tokenise(" ", FALSE);
int len = tokens.GetSize();
if (len == 0)
return TRUE;
PString cmd = tokens[0];
if ((len >= 2) && (cmd *= "play")) {
ogmChannel->QueueFile(tokens[1]);
if (len > 2) {
cmd = "menu";
tokens[1] = tokens[2];
}
}
if ((len >= 2) && (cmd *= "menu")) {
int newMenu = tokens[1].AsInteger();
if (newMenu != currentMenu)
StartMenu(newMenu);
}
else if (cmd *= "hangup")
ogmChannel->SetHangupTrigger();
else if (cmd *= "record")
ogmChannel->SetRecordTrigger();
return TRUE;
}
void MyH323Connection::OnUserInputChar(char ch)
{
if (ch == '#')
digits += '$';
else
digits += ch;
PTRACE(1, "Processing digit string " << digits);
ogmChannel->FlushQueue();
PString menuName = psprintf("%s%i", MENU_PREFIX, currentMenu);
if (menuNames.GetStringsIndex(menuName) == P_MAX_INDEX) {
PTRACE(1, "Cannot find menu " << menuName);
StartMenu(0);
return;
}
PConfig menu(menuName);
PStringList keys = menu.GetKeys();
PINDEX keyMatch = FindMatch(keys, digits);
// if key is still ambiguous, then keep collecting
if (keyMatch == 0)
return;
PString cmd;
if (keyMatch != P_MAX_INDEX) {
PString key = keys[keyMatch-1];
PTRACE(1, "Executing cmd for key " << key);
cmd = menu.GetString(key);
} else {
PTRACE(1, "Cannot match cmd " << digits << " in menu " << menuName);
cmd = menu.GetString("error", "menu 0");
}
if (!cmd.IsEmpty()) {
ProcessMenuCmd(cmd);
digits = "";
}
}
///////////////////////////////////////////////////////////////
BOOL CheckWAVFileValid(PWAVFile *chan, int type) {
// Check the wave file header
if (!chan->IsValid()) {
PTRACE(1, chan->GetName() << " wav file header invalid");
return FALSE;
}
// Check the wave file format
if ( (type == CHECK_PCM) && (chan->GetFormat() != 0x01) ){
PTRACE(1, chan->GetName() << " is not a PCM format wav file");
PTRACE(1, "It is format " << chan->GetFormat() );
return FALSE;
}
if ( (type == CHECK_G7231) &&
((chan->GetFormat() != 0x42) && (chan->GetFormat() != 0x111)) ){
PTRACE(1, chan->GetName() << " is not a G.723.1 format wav file");
PTRACE(1, "It is format " << chan->GetFormat() );
return FALSE;
}
// Check the sample rate for PCM wave files
if ( (type == CHECK_PCM) &&
( (chan->GetSampleRate() != 8000)
||(chan->GetChannels() != 1)
||(chan->GetSampleSize() != 16) )
) {
PTRACE(1, chan->GetName() << " is not a 16 Bit, Mono, 8000 Hz (8Khz) PCM wav file");
PTRACE(1, "It is " << chan->GetSampleSize() << " bits, "
<< (chan->GetChannels()==1 ? "mono " : "stereo ")
<< chan->GetSampleRate() << " Hz");
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////
PCM_OGMChannel::PCM_OGMChannel(MyH323Connection & _conn)
: conn(_conn)
{
silentCount = 20; // wait 20 frames before playing the OGM
recordTrigger = FALSE;
hangupTrigger = FALSE;
closed = FALSE;
playOnce = FALSE;
loopMessage = FALSE;
frameLen = frameOffs = 0;
}
void PCM_OGMChannel::PlayFile(PFile * chan)
{
PWaitAndSignal mutex(chanMutex);
if (!chan->Open(PFile::ReadOnly)) {
PTRACE(1, "Cannot open file \"" << chan->GetName() << "\"");
return;
}
PTRACE(1, "Playing file \"" << chan->GetName() << "\"");
totalData = 0;
SetReadChannel(chan, TRUE);
}
BOOL PCM_OGMChannel::IsWAVFileValid(PWAVFile *chan) {
// Check that this is a PCM wave file
return CheckWAVFileValid(chan, CHECK_PCM);
}
BOOL PCM_OGMChannel::Read(void * buffer, PINDEX amount)
{
PWaitAndSignal mutex(chanMutex);
// if the channel is closed, then return error
if (closed)
return FALSE;
// Create the frame buffer using the amount of bytes the codec wants to
// read. Different codecs use different read sizes.
frameBuffer.SetMinSize(1024);//amount);
// assume we are returning silence
BOOL doSilence = TRUE;
BOOL frameBoundary = FALSE;
// if still outputting a frame from last time, then keep doing it
if (frameOffs < frameLen) {
frameBoundary = AdjustFrame(buffer, amount);
doSilence = FALSE;
} else {
// if we are returning silence frames, then
if (silentCount > 0)
silentCount--;
// if a channel is already open, don't do silence
else if (GetBaseReadChannel() != NULL)
doSilence = FALSE;
// If not in silence and no existing channel, open a new file.
else {
PString * str = playQueue.Dequeue();
if (str != NULL) {
// check the file extension and open a .wav or a raw (.sw or .g723) file
if (((*str).Right(4)).ToLower() == ".wav") {
PWAVFile *chan = new PWAVFile(*str, PFile::ReadOnly);
if (!chan->IsOpen()) {
PTRACE(1, "Cannot open file \"" << chan->GetName() << "\"");
delete chan;
} else {
if (!IsWAVFileValid(chan) ) {
PTRACE(1, chan->GetName() << " is not a valid wav file");
delete chan;
cerr << "wave file is invalid" << endl;
} else {
PTRACE(1, "Playing file \"" << chan->GetName() << "\"");
totalData = 0;
SetReadChannel(chan, TRUE);
doSilence = FALSE;
}
if (loopMessage) {
PTRACE(1, "Looping file \"" << *str << "\"");
playQueue.Enqueue(new PString(*str));
}
}
} else { // raw file (eg .sw)
PFile *chan = new PFile(*str);
if (!chan->Open(PFile::ReadOnly)) {
PTRACE(1, "Cannot open file \"" << chan->GetName() << "\"");
delete chan;
} else {
PTRACE(1, "Playing file \"" << chan->GetName() << "\"");
totalData = 0;
SetReadChannel(chan, TRUE);
doSilence = FALSE;
}
}
delete str;
}
}
// if not doing silence, try and read from the file
if (!doSilence) {
if (ReadFrame(amount)) {
frameBoundary = AdjustFrame(buffer, amount);
totalData += amount;
} else {
PTRACE(1, "Finished playing " << totalData << " bytes");
PIndirectChannel::Close();
silentCount = 5; // always do 5 frames of silence after every file
// hangup if required
if (hangupTrigger || playOnce)
conn.ClearCall();
// trigger record if required
else if (recordTrigger) {
if ((playQueue.GetSize() == 0) && (GetBaseReadChannel() == NULL))
conn.StartRecording();
}
// no silence
doSilence = TRUE;
}
}
}
// start silence frame if required
if (doSilence) {
CreateSilenceFrame(amount);
frameBoundary = AdjustFrame(buffer, amount);
}
// delay to synchronise to frame boundary
if (frameBoundary)
Synchronise(amount);
return TRUE;
}
BOOL PCM_OGMChannel::Close()
{
PWaitAndSignal mutex(chanMutex);
closed = TRUE;
PIndirectChannel::Close();
return TRUE;
}
void PCM_OGMChannel::SetRecordTrigger()
{
PWaitAndSignal mutex(chanMutex);
recordTrigger = TRUE;
if ((playQueue.GetSize() == 0) && (GetBaseReadChannel() == NULL))
conn.StartRecording();
}
void PCM_OGMChannel::SetHangupTrigger()
{
PWaitAndSignal mutex(chanMutex);
hangupTrigger = TRUE;
if (GetBaseReadChannel() == NULL)
conn.ClearCall();
}
void PCM_OGMChannel::QueueFile(const PString & fn)
{
PWaitAndSignal mutex(chanMutex);
PTRACE(1, "Enqueueing file " << fn << " for playing");
playQueue.Enqueue(new PString(fn));
}
void PCM_OGMChannel::FlushQueue()
{
PWaitAndSignal mutex(chanMutex);
if (GetBaseReadChannel() != NULL) {
PIndirectChannel::Close();
if (hangupTrigger)
conn.ClearCall();
else if (recordTrigger)
conn.StartRecording();
}
PString * str;
while ((str = playQueue.Dequeue()) != NULL)
delete str;
}
BOOL PCM_OGMChannel::AdjustFrame(void * buffer, PINDEX amount)
{
// reduce read size for very short frame
if ((amount > frameLen) && (frameOffs == 0))
amount = frameLen;
if ((frameOffs + amount) > frameLen) {
cerr << "Reading past end of frame:offs=" << frameOffs << ",amt=" << amount << ",len=" << frameLen << endl;
return TRUE;
}
//PAssert((frameOffs + amount) <= frameLen, "Reading past end of frame");
memcpy(buffer, frameBuffer.GetPointer()+frameOffs, amount);
frameOffs += amount;
lastReadCount = amount;
return frameOffs == frameLen;
}
void PCM_OGMChannel::Synchronise(PINDEX amount)
{
ogm_delay.Delay(amount / 16);
}
BOOL PCM_OGMChannel::ReadFrame(PINDEX amount)
{
frameOffs = 0;
frameLen = amount;
BOOL result = PIndirectChannel::Read(frameBuffer.GetPointer(), frameLen);
// if we did not read a full frame of audio, fill the end of the
// frame with zeros.
PINDEX count = GetLastReadCount();
if (count < frameLen)
memset(frameBuffer.GetPointer()+count, 0, frameLen-count);
return result;
}
void PCM_OGMChannel::CreateSilenceFrame(PINDEX amount)
{
frameOffs = 0;
frameLen = amount;
memset(frameBuffer.GetPointer(), 0, frameLen);
}
///////////////////////////////////////////////////////////////
G7231_OGMChannel::G7231_OGMChannel(MyH323Connection & conn)
: PCM_OGMChannel(conn)
{
}
void G7231_OGMChannel::Synchronise(PINDEX /*amount*/)
{
ogm_delay.Delay(30);
}
BOOL G7231_OGMChannel::ReadFrame(PINDEX /*amount*/)
{
if (!PIndirectChannel::Read(frameBuffer.GetPointer(), 1))
return FALSE;
frameOffs = 0;
frameLen = G7231_File_Codec::GetFrameLen(frameBuffer[0]);
return PIndirectChannel::Read(frameBuffer.GetPointer()+1, frameLen-1);
}
void G7231_OGMChannel::CreateSilenceFrame(PINDEX /*amount*/)
{
frameOffs = 0;
frameLen = 4;
frameBuffer[0] = 2;
memset(frameBuffer.GetPointer()+1, 0, 3);
}
BOOL G7231_OGMChannel::IsWAVFileValid(PWAVFile *chan) {
// Check that this is a G.723.1 wave file
return CheckWAVFileValid(chan, CHECK_G7231);
}
///////////////////////////////////////////////////////////////
TimeLimitedVideoChanne
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -