I'm writing voice communicator. I have to control program from console, because we decided not to develop GUI - it's not important and it takes time. So, there is a thread which handles user commands from console:
void* ClientApp::commandHandler(void)
{
std::string input;
std::string connPort;
std::string connAddr;
std::map<std::string, int> mapStringValues;
mapStringValues["connect to server"] = 1;
mapStringValues["connect to host"] = 2;
mapStringValues["disconnect from server"] = 3;
mapStringValues["start call"] = 4;
mapStringValues["end call"] = 5;
mapStringValues["set TCP port"] = 6;
mapStringValues["help"] = 7;
mapStringValues["exit"] = 8;
std::cout << "Write command" << std::endl;
//int i = 0;
while(true)
{
//std::cout<< ++i<<std::endl;
std::getline(std::cin, input);
switch(mapStringValues[input])
{
case 1: //connect to server
std::cout << "TODO: connect to server" << std::endl;
break;
case 2: //connect to host
std::cout << "IP:" << std::endl;
std::getline(std::cin, connAddr);
std::cout << "port:" << std::endl;
std::getline(std::cin, connPort);
connectToHost(connAddr, std::stoi(connPort));
break;
case 3: //disconnect from server
std::cout << "TODO: disconnect from server" << std::endl;
break;
case 4: //call
if(callInProgres == true)
{
break;
}
networkController->udpConnect();
startCallViaNet();
break;
case 5: //end call
endCallViaNet();
break;
case 6:
break;
case 7:
showCommands();
break;
case 8:
audioPlayer->stopThread();
audioRecorder->stopThread();
networkController->stopSendUDPThread();
networkController->stopRecvUDPThread();
networkController->stopRecvTCPThread();
networkController->shutdownUdpConnection();
networkController->shutdownTcpConnection();
exit(0);
break;
}
}
}
Problem appears when I have to accept incoming call. I need the input so I can write yes or no. Thread which handles internet connection calls function which asks and gets answer (y/n). Next actions depend on what acceptCall function returned. I know it can cause trouble - many threads asking for input. So to prevent it, before thread calls this function, it terminates commandHandler thread(it's pthread and I cancel it - maybe not elegant, but works fine), gets input and then start again commandHandler:
int ClientApp::acceptCall(std::string ip)
{
std::cout << "Start call from "<<ip<<"? (y/n)" << std::endl;
char c = (char)getchar(); /* std::cin, getline, scanf... - I tied it*/
if(c == 'y'){
return 0;
}
else{
return -1;
}
}
And then something strange happens when I reject call and it starts commandHandler again. First getline from commandHandler is not waitng for input anymore. Loop starts working and no input is possible. I was trying all combinations of std::cin.ignore() and std::cin.clear(), all possible input functions. The best what I succeeded was blocking getline after another commandHandler start, but my commands didn't match any case in switch - commands were proper, but nothing, except one loop cycle happend after input. I'm going mad with this. I read hundreds of threads about C++ input but nothing helps me.
Aucun commentaire:
Enregistrer un commentaire