// File: rtoolbar.cpp #include "precomp.h" #include "RToolbar.h" #include "GenContainers.h" #include "GenControls.h" #include "Conf.h" #include "ConfRoom.h" #include "RoomList.h" #include "particip.h" #include "VidView.h" #include "ProgressBar.h" #include "AudioCtl.h" #include "CallingBar.h" #include "resource.h" #include "topWindow.h" #include "dlgCall2.h" #include "ulswizrd.h" #include "audiowiz.h" #include "sdialdlg.h" #include "callto.h" #define ZeroArray(_a) ZeroMemory(_a, sizeof(_a)) static void ShiftFocus(HWND hwndTop, BOOL bForward); class CRemoteVideo : public CVideoWindow { public: CRemoteVideo(BOOL bEmbedded = FALSE) : CVideoWindow(REMOTE, bEmbedded) { } // Stick the child in the lower-right corner of the window virtual void Layout() { CVideoWindow::Layout(); HWND hwnd = GetWindow(); HWND hwndLocal = GetFirstChild(hwnd); if (NULL != hwndLocal) { RECT rcRemote; GetClientRect(hwnd, &rcRemote); int left = rcRemote.right *5/8; int top = rcRemote.bottom *5/8; SetWindowPos(hwndLocal, NULL, left, top, rcRemote.right-left, rcRemote.bottom-top, SWP_NOZORDER); } } } ; // This just exists to send WM_NOTIFY messages back to the Roster class CRosterParent : public CFillWindow { private: CRoomListView *m_pRoster; void OnContextMenu(HWND hwnd, HWND hwndContext, UINT xPos, UINT yPos) { POINT pt = { xPos, yPos }; CRoomListView *pView = GetRoster(); if ((NULL != pView) && (pView->GetHwnd() == hwndContext)) { pView->OnPopup(pt); } FORWARD_WM_CONTEXTMENU(hwnd, hwndContext, xPos, yPos, CFillWindow::ProcessMessage); } inline LRESULT RosterNotify(CRoomListView *pRoster, UINT uMsg, WPARAM wParam, LPARAM lParam) { return(pRoster->OnNotify(wParam, lParam)); } // Just forward to the Roster LRESULT OnNotify(HWND hwnd, int id, NMHDR *pHdr) { // pass on all notifications: if (ID_LISTVIEW == pHdr->idFrom) { CRoomListView *pView = GetRoster(); if (NULL != pView) { // Forward to the roster return(FORWARD_WM_NOTIFY(pView, id, pHdr, RosterNotify)); } } return(FORWARD_WM_NOTIFY(hwnd, id, pHdr, CFillWindow::ProcessMessage)); } protected: ~CRosterParent() { // delete can handle NULL delete m_pRoster; } virtual LRESULT ProcessMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { HANDLE_MSG(hwnd, WM_NOTIFY, OnNotify); HANDLE_MSG(hwnd, WM_CONTEXTMENU, OnContextMenu); case WM_DESTROY: delete m_pRoster; m_pRoster = NULL; break; } return(CFillWindow::ProcessMessage(hwnd, uMsg, wParam, lParam)); } public: CRosterParent() : m_pRoster(NULL) {} BOOL Create(HWND hwndParent) { m_pRoster = new CRoomListView(); if (NULL == m_pRoster) { return(FALSE); } if (!CFillWindow::Create(hwndParent, 0)) { return(FALSE); } return(m_pRoster->Create(GetWindow())); } CRoomListView *GetRoster() const { return(m_pRoster); } } ; CToolbar *CreateToolbar( CGenWindow *pParent, const Buttons buttons[]=NULL, int nButtons=0, LPARAM lHideModes=0, DWORD dwExStyle=0 ); #define ReleaseIt(pUnk) if (NULL != (pUnk)) { (pUnk)->Release(); (pUnk) = NULL; } enum CheckStates { Unchecked = 0, Checked = 1, } ; const static int MainHMargin = 8; const static int MainVMargin = 5; const static int MainGap = 4; const static int SunkenHMargin = 8; const static int SunkenVMargin = 2; const static int ButtonsGap = 12; const static int AudioMax = 100; const static int AudioVolMax = 0xffff; const static int AudioBump = 10; enum MainTimers { IDT_AUDIO = 1, } ; // Set these bits in the hide mode to hide in certain situations enum HideModes { Inherit = 0x0000, Normal = 0x0001, Compact = 0x0002, DataOnly = 0x0004, NoAVTB = 0x0008, Roster = 0x0010, AudioTuning = 0x0020, Dialing = 0x0040, Receiving = 0x0080, ReceivingWPiP = 0x0100, Previewing = 0x0200, Video = Receiving|ReceivingWPiP|Previewing, Ignore = 0x4000, IfNoChildren = 0x8000, } ; // Sets the hide mode bits on a window static inline void SetHideModes(CGenWindow *pWin, LPARAM modes) { if (NULL != pWin) { pWin->SetUserData(modes); } } // Gets the hide mode bits on a window static inline LPARAM GetHideModes(IGenWindow *pWin) { return(pWin->GetUserData()); } CMainUI::CMainUI() : m_hbBack(NULL), m_eViewMode(ViewNormal), m_pLocalVideo(NULL), m_pRemoteVideo(NULL), m_pAudioMic(NULL), m_pAudioSpeaker(NULL), m_pRoster(NULL), m_pCalling(NULL), m_bDialing(FALSE), m_bAudioTuning(FALSE), m_bPreviewing(TRUE), m_bPicInPic(FALSE), m_bStateChanged(FALSE), m_bShowAVTB(FALSE) { } CMainUI::~CMainUI() { if (NULL != m_hbBack) { DeleteObject(m_hbBack); m_hbBack = NULL; } ReleaseIt(m_pLocalVideo); ReleaseIt(m_pRemoteVideo); ReleaseIt(m_pAudioMic); ReleaseIt(m_pAudioSpeaker); ReleaseIt(m_pRoster); ReleaseIt(m_pCalling); } void SplitBitmap(UINT nCols, UINT nRows, HBITMAP hbmSrc, HBITMAP hbmDst[]) { BITMAP bm; GetObject(hbmSrc, sizeof(bm), &bm); int nWid = bm.bmWidth / nCols; int nHgt = bm.bmHeight / nRows; HDC hdcScreen = GetDC(NULL); HDC hdcSrc = CreateCompatibleDC(hdcScreen); HDC hdcDst = CreateCompatibleDC(hdcScreen); ReleaseDC(NULL, hdcScreen); if (NULL != hdcSrc && NULL != hdcDst) { SelectObject(hdcSrc, hbmSrc); for(UINT i=0; iGetWindow(); for (int i=0; iCreate(hwnd, buttons[i].idCommand, _Module.GetModuleInstance(), buttons[i].idbStates, bTranslateColors, buttons[i].nInputStates, buttons[i].nCustomStates, pNotify)) { pButton->Release(); continue; } // Save off the created button if requested if (NULL != pCreated) { // HACKHACK georgep: Not AddRef'ing; will let caller do that if interested pCreated[i] = pButton; } if (0 != buttons[i].idTooltip) { pButton->SetTooltip(RES2T(buttons[i].idTooltip)); } // By default, do not hide individual buttons SetHideModes(pButton, Ignore); // Release our reference to the button pButton->Release(); } } CToolbar *CreateToolbar( CGenWindow *pParent, const Buttons buttons[], int nButtons, LPARAM lHideModes, DWORD dwExStyle ) { CToolbar *ret; ret = new CToolbar(); if (NULL == ret) { return(NULL); } if (!ret->Create(pParent->GetWindow(), dwExStyle)) { ret->Release(); return(NULL); } SetHideModes(ret, lHideModes); AddButtons(ret, buttons, nButtons, TRUE); return(ret); } void CMainUI::CreateDialTB(CGenWindow *pParent) { // Create the toolbar m_pCalling = new CCallingBar(); if (NULL != m_pCalling) { SetHideModes(m_pCalling, Compact); m_pCalling->Create(pParent, m_pConfRoom); // m_pCalling->Release(); } } void CMainUI::CreateAppsTB(CGenWindow *pParent) { const static int AppsHMargin = 5; const static int AppsVMargin = 0; const static int AppsHGap = 11; static const Buttons appButtons[] = { { IDB_SHARE , CBitmapButton::Disabled+1, 1, ID_TB_SHARING , IDS_TT_TB_SHARING , }, { IDB_CHAT , CBitmapButton::Disabled+1, 1, ID_TB_CHAT , IDS_TT_TB_CHAT , }, { IDB_WHITEBOARD , CBitmapButton::Disabled+1, 1, ID_TB_NEWWHITEBOARD , IDS_TT_TB_NEWWHITEBOARD , }, { IDB_FILE_TRANSFER , CBitmapButton::Disabled+1, 1, ID_TB_FILETRANSFER , IDS_TT_TB_FILETRANSFER , }, } ; // Create the "data" buttons toolbar CToolbar *pApps = CreateToolbar(pParent, appButtons, ARRAY_ELEMENTS(appButtons), Compact); if (NULL != pApps) { // HACKHACK georgep: These numbers make it appear about right pApps->m_hMargin = AppsHMargin; pApps->m_vMargin = AppsVMargin; pApps->m_gap = AppsHGap; // pApps->m_bMinDesiredSize = TRUE; pApps->Release(); } } void CMainUI::CreateVideoAndAppsTB(CGenWindow *pParent, CreateViewMode eMode, BOOL bEmbedded) { CLayeredView::LayoutStyle lVidDialStyle = CLayeredView::Center; switch (eMode) { case CreateFull: case CreatePreviewOnly: case CreateRemoteOnly: case CreateTelephone: break; case CreatePreviewNoPause: case CreateRemoteNoPause: lVidDialStyle = CLayeredView::Fill; break; default: return; } // Create the toolbar CBorderWindow *pVideoAndCalling = new CBorderWindow(); if (NULL != pVideoAndCalling) { if (pVideoAndCalling->Create(pParent->GetWindow())) { SetHideModes(pVideoAndCalling, DataOnly); pVideoAndCalling->m_hGap = 4; pVideoAndCalling->m_vGap = 4; // This is the center part of the border window CLayeredView *pVidAndDial = new CLayeredView(); if (NULL != pVidAndDial) { if (pVidAndDial->Create(pVideoAndCalling->GetWindow())) { pVideoAndCalling->m_uParts |= CBorderWindow::Center; pVidAndDial->m_lStyle = lVidDialStyle; CGenWindow *pLocalParent = pVidAndDial; if (CreateFull == eMode || CreateTelephone == eMode ) { CreateDialingWindow(pVidAndDial); } if (CreateFull == eMode || CreateRemoteOnly == eMode || CreateRemoteNoPause == eMode ) { // Create the remote video window m_pRemoteVideo = new CRemoteVideo(bEmbedded); if (NULL != m_pRemoteVideo) { SetHideModes(m_pRemoteVideo, Dialing|Previewing|DataOnly); m_pRemoteVideo->Create(pVidAndDial->GetWindow(), GetPalette(), this); pLocalParent = m_pRemoteVideo; } } if (CreateFull == eMode || CreatePreviewOnly == eMode || CreatePreviewNoPause == eMode ) { // Create the local video window, even though we don't show it yet m_pLocalVideo = new CVideoWindow(CVideoWindow::LOCAL, bEmbedded); if (NULL != m_pLocalVideo) { SetHideModes(m_pLocalVideo, Dialing|Receiving|DataOnly); m_pLocalVideo->Create(pLocalParent->GetWindow(), GetPalette(), this); ShowWindow(m_pLocalVideo->GetWindow(), SW_HIDE); } } } pVidAndDial->Release(); } if (CreateFull == eMode || CreateTelephone == eMode ) { // create the toolbar static const Buttons abOsr2Calling[] = { { IDB_DIAL , CBitmapButton::Disabled+1, 1, ID_TB_NEW_CALL , IDS_TT_TB_NEW_CALL , }, { IDB_HANGUP , CBitmapButton::Disabled+1, 1, IDM_FILE_HANGUP, IDS_TT_FILE_HANGUP, }, { IDB_DIRECTORY, CBitmapButton::Disabled+1, 1, ID_TB_DIRECTORY, IDS_TT_TB_DIRECTORY, }, { IDB_SHOWAV , CBitmapButton::Hot+1, Checked+1, ID_TB_SHOWAVTB , IDS_TT_TB_SHOWAVTB , }, } ; CGenWindow *agwOsr2Calling[ARRAY_ELEMENTS(abOsr2Calling)]; // This is the right-hand part of the border window CToolbar *ptbOsr2Calling = CreateToolbar(pVideoAndCalling, NULL, 0, DataOnly); if (NULL != ptbOsr2Calling) { pVideoAndCalling->m_uParts |= CBorderWindow::Right; ptbOsr2Calling->m_bVertical = TRUE; ptbOsr2Calling->m_nAlignment = Center; ZeroArray(agwOsr2Calling); AddButtons(ptbOsr2Calling, abOsr2Calling, ARRAY_ELEMENTS(abOsr2Calling), TRUE, agwOsr2Calling); SetHideModes(agwOsr2Calling[0], Normal); SetHideModes(agwOsr2Calling[3], Normal); ptbOsr2Calling->m_uRightIndex = 3; ptbOsr2Calling->Release(); } } // This is the bottom part of the border window CreateAVTB(pVideoAndCalling, eMode); pVideoAndCalling->m_uParts |= CBorderWindow::Bottom; } pVideoAndCalling->Release(); } } void CMainUI::CreateAVTB(CGenWindow *pParent, CreateViewMode eMode) { switch (eMode) { case CreateFull: case CreatePreviewOnly: case CreateRemoteOnly: break; default: return; } const static int AVHMargin = 10; const static int AVVMargin = 2; const static int AVHGap = ButtonsGap; // create the toolbar static const Buttons avButtons[] = { { IDB_PLAYPAUSE, CBitmapButton::Disabled+1, 2, ID_TB_PLAYPAUSE , IDS_TT_TB_PLAYPAUSE , }, { IDB_PIP , CBitmapButton::Disabled+1, 1, ID_TB_PICINPIC , IDS_TT_TB_PICINPIC , }, { IDB_AUDIO , CBitmapButton::Disabled+1, Checked+1, ID_TB_AUDIOTUNING, IDS_TT_TB_AUDIOTUNING, }, } ; int nButtons = eMode == CreateFull ? ARRAY_ELEMENTS(avButtons) : 1; CToolbar *pAV = CreateToolbar(pParent, NULL, 0, NoAVTB|DataOnly); if (NULL != pAV) { CGenWindow *aButtons[ARRAY_ELEMENTS(avButtons)]; ZeroArray(aButtons); AddButtons(pAV, avButtons, nButtons, TRUE, aButtons); CGenWindow *pAT; // // If video is completely disabled by policy, disable video buttons // if (!FIsSendVideoAllowed() && !FIsReceiveVideoAllowed()) { pAT = aButtons[0]; if (NULL != pAT) { EnableWindow(pAT->GetWindow(), FALSE); } pAT = aButtons[1]; if (NULL != pAT) { EnableWindow(pAT->GetWindow(), FALSE); } } // // If audio is completely disabled by policy, disable audio buttons // pAT = aButtons[2]; if (NULL != pAT) { ASSERT(ID_TB_AUDIOTUNING == GetDlgCtrlID(pAT->GetWindow())); if (!FIsAudioAllowed()) { EnableWindow(pAT->GetWindow(), FALSE); } } pAV->m_hMargin = AVHMargin; pAV->m_vMargin = AVVMargin; pAV->m_gap = AVHGap; pAV->Release(); } } #if FALSE // { void CMainUI::CreateCallsTB(CGenWindow *pParent) { // create the toolbar static const Buttons callsButtons[] = { { IDB_INCOMING , CBitmapButton::Hot+1, 1, ID_TB_INCOMING , IDS_TT_TB_INCOMING , }, { IDB_HANGUP , CBitmapButton::Hot+1, 1, IDM_FILE_HANGUP , IDS_TT_FILE_HANGUP , }, { IDB_CREDENTIALS, CBitmapButton::Hot+1, 1, ID_TB_CREDENTIALS, IDS_TT_TB_CREDENTIALS, }, } ; CToolbar *pCalls = CreateToolbar(pParent, callsButtons, ARRAY_ELEMENTS(callsButtons), Compact); if (NULL != pCalls) { pCalls->Release(); } } #endif // FALSE } void CMainUI::CreateDialingWindow( CGenWindow *pParent // The parent window ) { const static int DialHMargin = 17; const static int DialVMargin = 4; const static int DialHGap = 5; const static int DialVGap = 0; CEdgedWindow *pEdge = new CEdgedWindow(); if (NULL == pEdge) { return; } SetHideModes(pEdge, Video|DataOnly); if (pEdge->Create(pParent->GetWindow())) { CToolbar *pDialing = CreateToolbar(pEdge, NULL, 0, Ignore); if (NULL != pDialing) { pDialing->m_bVertical = TRUE; pDialing->m_gap = DialVGap; pDialing->m_hMargin = DialHMargin; pDialing->m_vMargin = DialVMargin; static const Buttons dialButtons[] = { { IDB_DIAL1 , CBitmapButton::Hot+1, 1, ID_TB_DIAL1 , IDS_TT_DIALPAD, }, { IDB_DIAL2 , CBitmapButton::Hot+1, 1, ID_TB_DIAL2 , IDS_TT_DIALPAD, }, { IDB_DIAL3 , CBitmapButton::Hot+1, 1, ID_TB_DIAL3 , IDS_TT_DIALPAD, }, { IDB_DIAL4 , CBitmapButton::Hot+1, 1, ID_TB_DIAL4 , IDS_TT_DIALPAD, }, { IDB_DIAL5 , CBitmapButton::Hot+1, 1, ID_TB_DIAL5 , IDS_TT_DIALPAD, }, { IDB_DIAL6 , CBitmapButton::Hot+1, 1, ID_TB_DIAL6 , IDS_TT_DIALPAD, }, { IDB_DIAL7 , CBitmapButton::Hot+1, 1, ID_TB_DIAL7 , IDS_TT_DIALPAD, }, { IDB_DIAL8 , CBitmapButton::Hot+1, 1, ID_TB_DIAL8 , IDS_TT_DIALPAD, }, { IDB_DIAL9 , CBitmapButton::Hot+1, 1, ID_TB_DIAL9 , IDS_TT_DIALPAD, }, { IDB_DIALSTAR , CBitmapButton::Hot+1, 1, ID_TB_DIALSTAR , IDS_TT_DIALPAD, }, { IDB_DIAL0 , CBitmapButton::Hot+1, 1, ID_TB_DIAL0 , IDS_TT_DIALPAD, }, { IDB_DIALPOUND, CBitmapButton::Hot+1, 1, ID_TB_DIALPOUND, IDS_TT_DIALPAD, }, } ; for (int row=0; row<4; ++row) { CToolbar *pRowTB = CreateToolbar(pDialing); if (NULL != pRowTB) { pRowTB->m_gap = DialHGap; AddButtons(pRowTB, &dialButtons[row*3], 3, TRUE, NULL, this); pRowTB->Release(); } } pDialing->Release(); } } pEdge->Release(); } // Creates the audio-tuning window void CMainUI::CreateAudioTuningWindow( CGenWindow *pParent // The parent window ) { static const int ATHMargin = 8; static const int ATVMargin = 6; static const int ATControlWidth = 170; CToolbar *pATWindow = CreateToolbar(pParent, NULL, 0, NoAVTB|Roster|DataOnly); if (NULL != pATWindow) { pATWindow->m_bVertical = TRUE; pATWindow->m_nAlignment = Fill; pATWindow->m_gap = MainGap; CEdgedWindow *pEdge; pEdge = new CEdgedWindow(); if (NULL != pEdge) { pEdge->m_hMargin = ATHMargin; pEdge->m_vMargin = ATVMargin; if (pEdge->Create(pATWindow->GetWindow())) { SetHideModes(pEdge, Ignore); CButton *pButton = new CButton(); if (NULL != pButton) { pButton->Create(pEdge->GetWindow(), ID_TB_TUNEMIC_UNMUTE, NULL, BS_CHECKBOX|BS_ICON|WS_TABSTOP, this); pButton->SetTooltip(RES2T(IDS_TT_MUTE_MIC)); HICON hIcon = reinterpret_cast(LoadImage(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_MICFONE), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR)); pButton->SetIcon(hIcon); pEdge->SetHeader(pButton); pButton->Release(); } UpdateMuteState(FALSE, pButton); m_pAudioMic = new CProgressTrackbar(); if (NULL != m_pAudioMic) { if (m_pAudioMic->Create(pEdge->GetWindow(), 0, this)) { m_pAudioMic->SetTooltip(RES2T(IDS_TT_ADJUST_MIC)); m_pAudioMic->SetMaxValue(AudioMax); SIZE size; m_pAudioMic->GetDesiredSize(&size); size.cx = ATControlWidth; m_pAudioMic->SetDesiredSize(&size); } // m_pAudioMic->Release(); } } pEdge->Release(); } pEdge = new CEdgedWindow(); if (NULL != pEdge) { pEdge->m_hMargin = ATHMargin; pEdge->m_vMargin = ATVMargin; if (pEdge->Create(pATWindow->GetWindow())) { SetHideModes(pEdge, Ignore); CButton *pButton = new CButton(); if (NULL != pButton) { pButton->Create(pEdge->GetWindow(), ID_TB_TUNESPEAKER_UNMUTE, NULL, BS_CHECKBOX|BS_ICON|WS_TABSTOP, this); pButton->SetTooltip(RES2T(IDS_TT_MUTE_SPK)); HICON hIcon = reinterpret_cast(LoadImage(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_SPEAKER), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR)); pButton->SetIcon(hIcon); pEdge->SetHeader(pButton); pButton->Release(); } UpdateMuteState(TRUE, pButton); m_pAudioSpeaker = new CProgressTrackbar(); if (NULL != m_pAudioSpeaker) { if (m_pAudioSpeaker->Create(pEdge->GetWindow(), 0, this)) { m_pAudioSpeaker->SetTooltip(RES2T(IDS_TT_ADJUST_SPK)); m_pAudioSpeaker->SetMaxValue(AudioMax); SIZE size; m_pAudioSpeaker->GetDesiredSize(&size); size.cx = ATControlWidth; m_pAudioSpeaker->SetDesiredSize(&size); } // m_pAudioSpeaker->Release(); } } pEdge->Release(); } pATWindow->Release(); } CAudioControl *pAudioControl = GetAudioControl(); if (NULL != pAudioControl) { // Force an update of the controls OnAudioLevelChange(TRUE , pAudioControl->GetSpeakerVolume()); OnAudioLevelChange(FALSE, pAudioControl->GetRecorderVolume()); } } void CMainUI::CreateRosterArea(CGenWindow *pParent, CreateViewMode eMode) { switch (eMode) { case CreateFull: case CreateDataOnly: case CreateTelephone: break; default: return; } CLayeredView *pView = new CLayeredView(); if (NULL == pView) { // Pretty bad return; } if (pView->Create(pParent->GetWindow())) { SetHideModes(pView, IfNoChildren); pView->m_lStyle = CLayeredView::Fill; if (eMode != CreateDataOnly) { CreateAudioTuningWindow(pView); } if (eMode != CreateTelephone) { CToolbar *pRosterAndCall = CreateToolbar(pView); if (NULL != pRosterAndCall) { pRosterAndCall->m_nAlignment = CToolbar::Fill; m_pRoster = new CRosterParent(); if (NULL != m_pRoster) { m_pRoster->Create(pRosterAndCall->GetWindow()); // HACKHACK georgep: Just calling SetUserData directly for now SetHideModes(m_pRoster, Compact|AudioTuning); } if (CreateDataOnly != eMode) { CToolbar *pCalling = CreateToolbar(pRosterAndCall); if (NULL != pCalling) { SetHideModes(pCalling, Normal|Compact); pCalling->m_bVertical = TRUE; static const Buttons abCalling[] = { { IDB_HANGUP , CBitmapButton::Disabled+1, 1, IDM_FILE_HANGUP, IDS_TT_FILE_HANGUP, }, { IDB_DIRECTORY, CBitmapButton::Disabled+1, 1, ID_TB_DIRECTORY, IDS_TT_TB_DIRECTORY, }, } ; AddButtons(pCalling, abCalling, ARRAY_ELEMENTS(abCalling), TRUE, NULL, this); pCalling->Release(); } } pRosterAndCall->m_uRightIndex = 1; pRosterAndCall->m_bHasCenterChild = TRUE; pRosterAndCall->Release(); } } } pView->Release(); } BOOL CMainUI::Create( HWND hwndParent, CConfRoom *pConfRoom, CreateViewMode eMode, BOOL bEmbedded ) { // Store this away so we can call some methods in it later m_pConfRoom = pConfRoom; ASSERT(m_pConfRoom); if (NULL == m_pConfRoom) { return(FALSE); } // Create the window if (!CToolbar::Create(hwndParent)) { return(FALSE); } // Try to remain a little bit abstract CToolbar *pMain = this; m_pConfRoom->AddConferenceChangeHandler(this); // A vertical toolbar that fills all its area pMain->m_hMargin = MainHMargin; pMain->m_vMargin = MainVMargin; pMain->m_gap = MainGap; if (CreateRemoteNoPause == eMode || CreatePreviewNoPause == eMode ) { pMain->m_hMargin = 0; pMain->m_vMargin = 0; pMain->m_bHasCenterChild = TRUE; //HACKHACK This only works because all these views have only 1 window pMain->m_uRightIndex = 1; } pMain->m_bVertical = TRUE; pMain->m_nAlignment = Fill; m_hbBack = CGenWindow::GetStandardBrush(); // Create all the sub toolbars if (CreateFull == eMode || CreateTelephone == eMode ) { CreateDialTB(pMain); } CreateVideoAndAppsTB(pMain, eMode, bEmbedded); CreateRosterArea(pMain, eMode); if (CreateFull == eMode || CreateDataOnly == eMode ) { CreateAppsTB(pMain); } // Now we need to update to the current state of the conference if (m_pConfRoom->FIsConferenceActive()) { OnCallStarted(); CSimpleArray& lMembers = m_pConfRoom->GetParticipantList(); for (int i=lMembers.GetSize()-1; i>=0; --i) { OnChangeParticipant(lMembers[i], NM_MEMBER_ADDED); } // Need to tell everybody what the active channels are INmConference2 *pNmConf = m_pConfRoom->GetActiveConference(); if (NULL != pNmConf) { // Just in case pNmConf->AddRef(); IEnumNmChannel *pEnumCh; if (SUCCEEDED(pNmConf->EnumChannel(&pEnumCh))) { INmChannel *pChannel; ULONG uGot; while (S_OK == pEnumCh->Next(1, &pChannel, &uGot) && 1 == uGot) { OnVideoChannelChanged(NM_CHANNEL_ADDED, pChannel); pChannel->Release(); } pEnumCh->Release(); } pNmConf->Release(); } } if (CreateDataOnly == eMode) { SetDataOnly(TRUE); } if (CreateTelephone == eMode) { SetDialing(TRUE); SetAudioTuning(TRUE); } OnChangePermissions(); UpdateViewState(); UpdatePlayPauseState(); return(TRUE); } HBRUSH CMainUI::GetBackgroundBrush() { return(m_hbBack); } // REVIEW georgep: Should this loop until it gets an IGenWindow? HPALETTE CMainUI::GetPalette() { return(m_pConfRoom->GetPalette()); } // Recursive function to hide/show windows for the current view // Returns whether any of the children are visible BOOL ShowWindows( HWND hwndParent, // The parent window to start from LPARAM lDefMode, // The hide mode to use if Inherit LPARAM hideMode // The current hide mode ) { BOOL bRet = FALSE; for (HWND hwndChild=::GetWindow(hwndParent, GW_CHILD); NULL!=hwndChild; hwndChild=::GetWindow(hwndChild, GW_HWNDNEXT)) { IGenWindow *pChild = IGenWindow::FromHandle(hwndChild); if (NULL == pChild) { continue; } LPARAM lMode = GetHideModes(pChild); if (Ignore == lMode) { if ((GetWindowStyle(hwndChild)&WS_VISIBLE) != 0) { bRet = TRUE; } continue; } if (Inherit == lMode) { lMode = lDefMode; } // recurse to child windows first to avoid flicker LPARAM lNoChildren = ShowWindows(hwndChild, lMode, hideMode) ? 0 : IfNoChildren; // If any of the hide mode bits are set, then hide the window // otherwise show it BOOL bShow = ((lMode&(hideMode|lNoChildren)) == 0); if (bShow) { bRet = TRUE; } ShowWindow(hwndChild, bShow ? SW_SHOW : SW_HIDE); } return(bRet); } BOOL CMainUI::CanPreview() { HWND hwndLocal = GetVideoWindow(TRUE); return(NULL!=hwndLocal && GetLocalVideo()->IsXferAllowed()); } void CMainUI::UpdateViewState() { // Put together all the modes we ARE in, and hide any windows that want // to be hidden while in one of those modes // The default mode LPARAM hideModes; if (IsCompact()) { hideModes = Compact; if (!IsShowAVTB()) { hideModes |= NoAVTB; } } else if (IsDataOnly()) { hideModes = DataOnly; } else { hideModes = Normal; } if (IsDialing()) { hideModes |= Dialing; } else { // hwndRemote will be NULL for PreviewOnly mode HWND hwndRemote = GetVideoWindow(FALSE); if (NULL == hwndRemote) { hideModes |= Previewing; } else { HWND hwndLocal = GetVideoWindow(TRUE); BOOL bPreviewing = IsPreviewing(); HWND parent = NULL; BOOL bZoomable; LONG style = GetWindowLong(hwndLocal, GWL_EXSTYLE); if (bPreviewing) { hideModes |= Previewing; parent = GetParent(hwndRemote); style |= WS_EX_CLIENTEDGE; bZoomable = TRUE; } else { hideModes |= (m_bPicInPic && CanPreview()) ? ReceivingWPiP : Receiving; parent = hwndRemote; style &= ~WS_EX_CLIENTEDGE; bZoomable = FALSE; } if (GetParent(hwndLocal) != parent) { SetWindowLong(hwndLocal, GWL_EXSTYLE, style); SetParent(hwndLocal, parent); SetWindowPos(hwndLocal, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); CVideoWindow *pVideo = GetLocalVideo(); if (NULL != pVideo) { pVideo->SetZoomable(bZoomable); } } } } // Enable/disable the PiP window IGenWindow *pPiP = FindControl(ID_TB_PICINPIC); if (NULL != pPiP) { CComPtr spButton = com_cast(pPiP); BOOL bEnable = !IsPreviewing() && CanPreview() && !IsDialing(); EnableWindow(spButton->GetWindow(), bEnable); } hideModes |= IsAudioTuning() && !IsDataOnly() ? AudioTuning : Roster; HWND hwnd = GetWindow(); ShowWindows(hwnd, 0, hideModes); // If the focus is on a child window which is now not visible, but we are, // then change the focus to this window if (!IsWindowVisible(GetFocus()) && IsWindowActive(hwnd) && IsWindowVisible(hwnd)) { SetFocus(hwnd); } IGenWindow *pButton = FindControl(ID_TB_AUDIOTUNING); CComPtr spButton = com_cast(pButton); if (spButton) { BOOL bAudioTuning = IsAudioTuning() && !IsCompact(); spButton->SetCustomState(bAudioTuning ? Checked : Unchecked); spButton->SetTooltip(RES2T(bAudioTuning ? IDS_TT_TB_SHOWROSTER : IDS_TT_TB_AUDIOTUNING)); } OnDesiredSizeChanged(); } void CMainUI::SetCompact(BOOL bCompact) { bCompact = bCompact != FALSE; if (IsCompact() == bCompact) { // Nothing to do return; } m_eViewMode = bCompact ? ViewCompact : ViewNormal; UpdateViewState(); } void CMainUI::SetDataOnly(BOOL bDataOnly) { bDataOnly = bDataOnly != FALSE; if (IsDataOnly() == bDataOnly) { // Nothing to do return; } m_eViewMode = bDataOnly ? ViewDataOnly : ViewNormal; UpdateViewState(); } void CMainUI::SetDialing(BOOL bDialing) { bDialing = bDialing != FALSE; if (IsDialing() == bDialing) { // Nothing to do return; } m_bDialing = bDialing; UpdateViewState(); } void CMainUI::SetPicInPic(BOOL bPicInPic) { bPicInPic = bPicInPic != FALSE; if (IsPicInPic() == bPicInPic) { // Nothing to do return; } m_bPicInPic = bPicInPic; UpdateViewState(); } BOOL CMainUI::IsPicInPicAllowed() { return(!IsDataOnly() && !m_bPreviewing && CanPreview()); } void CMainUI::SetAudioTuning(BOOL bAudioTuning) { if ((IsAudioTuning() && bAudioTuning) || (!IsAudioTuning() && !bAudioTuning)) { // Nothing to do return; } m_bAudioTuning = bAudioTuning; if (IsAudioTuning()) { SetTimer(GetWindow(), IDT_AUDIO, AUDIODLG_MIC_TIMER_PERIOD, NULL); } else { KillTimer(GetWindow(), IDT_AUDIO); } UpdateViewState(); } void CMainUI::SetShowAVTB(BOOL bShowAVTB) { if ((IsShowAVTB() && bShowAVTB) || (!IsShowAVTB() && !bShowAVTB)) { // Nothing to do return; } m_bShowAVTB = bShowAVTB; UpdateViewState(); } LRESULT CMainUI::ProcessMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static const UINT c_uMsgMSWheel = ::IsWindowsNT() ? WM_MOUSEWHEEL : ::RegisterWindowMessage(_TEXT("MSWHEEL_ROLLMSG")); switch (message) { HANDLE_MSG(hwnd, WM_TIMER , OnTimer); HANDLE_MSG(hwnd, WM_DESTROY , OnDestroy); case WM_CREATE: { // Allow dialog-like keyboard support HACCEL hAccel = LoadAccelerators(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDR_MAINUI)); if (NULL != hAccel) { m_pAccel = new CTranslateAccelTable(hwnd, hAccel); if (NULL != m_pAccel) { AddTranslateAccelerator(m_pAccel); } } break; } case WM_SETFOCUS: ShiftFocus(GetWindow(), TRUE); break; default: if (message == c_uMsgMSWheel) { CRoomListView *pView = GetRoster(); if (NULL != pView) { ::SendMessage(pView->GetHwnd(), message, wParam, lParam); } break; } break; } return(CToolbar::ProcessMessage(hwnd, message, wParam, lParam)); } void CMainUI::OnScroll(CProgressTrackbar *pTrackbar, UINT code, int pos) { BOOL bSpeaker = FALSE; if (m_pAudioSpeaker == pTrackbar) { bSpeaker = TRUE; } else if (m_pAudioMic == pTrackbar) { } else { // I don't think we should get here return; } // Can't trust the pos passed in pos = pTrackbar->GetTrackValue(); CAudioControl *pAudioControl = GetAudioControl(); if (NULL == pAudioControl) { return; } DWORD dwVolume = (pos*AudioVolMax + AudioMax/2)/AudioMax; dwVolume = min(max(dwVolume, 0), AudioVolMax); if (bSpeaker) { pAudioControl->SetSpeakerVolume(dwVolume); } else { pAudioControl->SetRecorderVolume(dwVolume); } } HWND CMainUI::GetVideoWindow(BOOL bLocal) { CVideoWindow *pVideo = bLocal ? GetLocalVideo() : GetRemoteVideo(); return(NULL == pVideo ? NULL : pVideo->GetWindow()); } void CMainUI::ToggleMute(BOOL bSpeaker) { CAudioControl *pAudioControl = GetAudioControl(); if (NULL != pAudioControl) { BOOL bMuted = bSpeaker ? pAudioControl->IsSpkMuted() : pAudioControl->IsRecMuted(); pAudioControl->MuteAudio(bSpeaker, !bMuted); } } void CMainUI::UpdateMuteState(BOOL bSpeaker, CButton *pButton) { CAudioControl *pAudioControl = GetAudioControl(); if (NULL != pAudioControl) { BOOL bMuted = bSpeaker ? pAudioControl->IsSpkMuted() : pAudioControl->IsRecMuted(); pButton->SetChecked(!bMuted); } } void CMainUI::BumpAudio(BOOL bSpeaker, int pct) { CAudioControl *pAudioControl = GetAudioControl(); if (NULL != pAudioControl) { int dwVolume = static_cast(bSpeaker ? pAudioControl->GetSpeakerVolume() : pAudioControl->GetRecorderVolume()); dwVolume += (pct*AudioVolMax/100); dwVolume = min(max(dwVolume, 0), AudioVolMax); if (bSpeaker) { pAudioControl->SetSpeakerVolume(dwVolume); } else { pAudioControl->SetRecorderVolume(dwVolume); } } } void CMainUI::SetAudioProperty(BOOL bSpeaker, NM_AUDPROP uID, ULONG uValue) { CAudioControl *pAudioControl = GetAudioControl(); if (NULL != pAudioControl) { pAudioControl->SetProperty(bSpeaker, uID, uValue); } } // IButtonChange void CMainUI::OnClick(CButton *pButton) { HWND hwndCtl = pButton->GetWindow(); OnCommand(GetWindow(), GetWindowLong(hwndCtl, GWL_ID), hwndCtl, BN_CLICKED); } void CMainUI::OnInitMenu(HMENU hMenu) { CVideoWindow *pVideo = IsPreviewing() ? GetLocalVideo() : GetRemoteVideo(); if (NULL != pVideo) { pVideo->UpdateVideoMenu(hMenu); pVideo = GetLocalVideo(); EnableMenuItem(hMenu, IDM_VIDEO_UNDOCK, MF_BYCOMMAND|(NULL != pVideo && pVideo->IsXferAllowed() ? MF_ENABLED : MF_GRAYED|MF_DISABLED)); } } static void AppendText(CCallingBar *pCalling, TCHAR cAdd) { if (NULL != pCalling) { // I don't want to change a string that you can't see if (IsWindowVisible(pCalling->GetWindow())) { TCHAR szText[] = TEXT("0"); szText[0] = cAdd; TCHAR szTemp[MAX_PATH]; int nLen = pCalling->GetText(szTemp, ARRAY_ELEMENTS(szTemp)); if (nLen + lstrlen(szText) <= ARRAY_ELEMENTS(szTemp) - 1) { lstrcat(szTemp, szText); pCalling->SetText(szTemp); } } } } static BOOL ShouldTry(HWND child) { // REVIEW georgep: I could look at WS_EX_CONTROLPARENT also return((WS_VISIBLE) == (GetWindowStyle(child) & (WS_DISABLED|WS_VISIBLE))); } static BOOL IsTabbable(HWND child) { return((WS_TABSTOP|WS_VISIBLE) == (GetWindowStyle(child) & (WS_TABSTOP|WS_DISABLED|WS_VISIBLE))); } // BUGBUG georgep: I should move this into CGenWindow // Determine the next control in the tab order static HWND NextControl(HWND hwndTop, HWND hwndFocus) { // Loop detection stuff BOOL bGotToTop = FALSE; // We'll loop to avoid really deep recursion while (TRUE) { // First try the children of hwndFocus if (hwndFocus == hwndTop || ShouldTry(hwndFocus)) { HWND next = GetFirstChild(hwndFocus); if (NULL != next) { if (IsTabbable(next)) { return(next); } hwndFocus = next; continue; } } if (hwndFocus == hwndTop) { // Apparently hwndTop has no children return(NULL); } HWND next; while (NULL == (next = GetNextSibling(hwndFocus))) { hwndFocus = GetParent(hwndFocus); if (NULL == hwndFocus) { // Invalid params return(NULL); } if (hwndTop == hwndFocus) { break; } } if (hwndTop == hwndFocus) { // Detect if we have looped back to the top again if (bGotToTop) { return(NULL); } bGotToTop = TRUE; continue; } if (IsTabbable(next)) { return(next); } hwndFocus = next; } // We looped back to the beginning, so I guess nobody can take the focus return(NULL); } // Determine the previous control in the tab order static HWND PrevControl(HWND hwndTop, HWND hwndFocus) { // LAZYLAZY georgep: It's hard to do this directly, so I'll just loop // on the NextControl. It should be fast enough. // In case hwndFocus is not focusable for some reason, we still need to // detect the loop HWND hwndStart = NextControl(hwndTop, hwndFocus); // HACK for combo boxes: go from the edit control to the combo box control while (NULL != hwndFocus && hwndTop != hwndFocus && !IsTabbable(hwndFocus) ) { hwndFocus = GetParent(hwndFocus); } HWND ret = hwndStart; while (TRUE) { HWND next = NextControl(hwndTop, ret); if (NULL == next) { // Oops! return(NULL); } if (hwndFocus == next || hwndStart == next ) { break; } ret = next; } return(ret); } static void ShiftFocus(HWND hwndTop, BOOL bForward) { HWND hwndFocus = GetFocus(); if (!IsWindowActive(hwndTop)) { hwndFocus = hwndTop; } HWND next = bForward ? NextControl(hwndTop, hwndFocus) : PrevControl(hwndTop, hwndFocus); if (NULL != next) { SetFocus(next); } else { MessageBeep(MB_ICONHAND); } } void CMainUI::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { switch (id) { case ID_NAV_TAB: ShiftFocus(hwnd, TRUE); break; case ID_NAV_SHIFT_TAB: ShiftFocus(hwnd, FALSE); break; case IDM_VIEW_DIALPAD: SetDialing(!IsDialing()); break; case ID_TB_PICINPIC: SetPicInPic(!IsPicInPic()); break; case ID_TB_REJECT: case ID_TB_CREDENTIALS: break; case ID_TB_AUDIOTUNING: { m_bStateChanged = TRUE; SetAudioTuning(!IsAudioTuning()); break; } case ID_TB_SHOWAVTB: { m_bStateChanged = TRUE; SetShowAVTB(!IsShowAVTB()); CComPtr spButton = com_cast(IGenWindow::FromHandle(hwndCtl)); if (spButton) { BOOL bShow = IsShowAVTB(); spButton->SetCustomState(bShow ? Checked : Unchecked); spButton->SetTooltip(RES2T(bShow ? IDS_TT_TB_HIDEAVTB : IDS_TT_TB_SHOWAVTB)); } break; } case ID_TB_TUNEMIC_UNMUTE: ToggleMute(FALSE); break; case ID_TB_TUNESPEAKER_UNMUTE: ToggleMute(TRUE); break; case ID_TB_DIAL0: case ID_TB_DIAL1: case ID_TB_DIAL2: case ID_TB_DIAL3: case ID_TB_DIAL4: case ID_TB_DIAL5: case ID_TB_DIAL6: case ID_TB_DIAL7: case ID_TB_DIAL8: case ID_TB_DIAL9: SetAudioProperty(FALSE, NM_AUDPROP_DTMF_DIGIT, id-ID_TB_DIAL0); AppendText(m_pCalling, '0'+id-ID_TB_DIAL0); break; case ID_TB_DIALSTAR: SetAudioProperty(FALSE, NM_AUDPROP_DTMF_DIGIT, 10); AppendText(m_pCalling, '*'); break; case ID_TB_DIALPOUND: SetAudioProperty(FALSE, NM_AUDPROP_DTMF_DIGIT, 11); AppendText(m_pCalling, '#'); break; case ID_TB_DIRECTORY: { CFindSomeone::findSomeone(m_pConfRoom); } break; case ID_TB_PLAYPAUSE: TogglePlayPause(); break; case IDM_VIDEO_ZOOM1: case IDM_VIDEO_ZOOM2: case IDM_VIDEO_ZOOM3: case IDM_VIDEO_ZOOM4: case IDM_VIDEO_UNDOCK: case IDM_VIDEO_GETACAMERA: { CVideoWindow *pVideo = IsPreviewing() ? GetLocalVideo() : GetRemoteVideo(); if (NULL != pVideo) { pVideo->OnCommand(id); } break; } case IDM_POPUP_EJECT: case IDM_POPUP_PROPERTIES: case IDM_POPUP_SPEEDDIAL: case IDM_POPUP_ADDRESSBOOK: case IDM_POPUP_GIVECONTROL: case IDM_POPUP_CANCELGIVECONTROL: { CRoomListView *pView = GetRoster(); if (NULL != pView) { CParticipant * pPart = pView->GetParticipant(); if (NULL != pPart) { pPart->OnCommand(hwnd, (WORD)id); } } break; } case ID_FILE_CREATE_SPEED_DIAL: { TCHAR szAddress[MAX_EMAIL_NAME_LENGTH + MAX_SERVER_NAME_LENGTH + 1]; LPCTSTR pszAddress = NULL; CRoomListView *pView = GetRoster(); if (NULL != pView) { CParticipant * pPart = pView->GetParticipant(); if (NULL != pPart) { if (S_OK == pPart->GetUlsAddr(szAddress, CCHMAX(szAddress))) { pszAddress = szAddress; } } } CSpeedDialDlg sdd(hwnd, NM_ADDR_ULS); sdd.DoModal(pszAddress); break; } case ID_TB_CHAT: case ID_TB_NEWWHITEBOARD: case ID_TB_SHARING: case ID_TB_NEW_CALL: default: m_pConfRoom->OnCommand(hwnd, id, hwndCtl, codeNotify); break; } } void CMainUI::OnDestroy(HWND hwnd) { if (NULL != m_pConfRoom) { m_pConfRoom->RemoveConferenceChangeHandler(this); } if (NULL != m_pAccel) { RemoveTranslateAccelerator(m_pAccel); m_pAccel->Release(); m_pAccel = NULL; } } BOOL CMainUI::OnQueryEndSession() { CMainUI::OnClose(); return(TRUE); } void CMainUI::OnClose() { CVideoWindow *pLocal = GetLocalVideo(); if (NULL != pLocal) { pLocal->Pause(TRUE); } } VOID CMainUI::SaveSettings() { CVideoWindow *pVideo; pVideo = GetLocalVideo(); if (NULL != pVideo) { pVideo->SaveSettings(); } pVideo = GetRemoteVideo(); if (NULL != pVideo) { pVideo->SaveSettings(); } } VOID CMainUI::ForwardSysChangeMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { CVideoWindow *pVideo; pVideo = GetLocalVideo(); if (NULL != pVideo) { pVideo->ForwardSysChangeMsg(uMsg, wParam, lParam); } pVideo = GetRemoteVideo(); if (NULL != pVideo) { pVideo->ForwardSysChangeMsg(uMsg, wParam, lParam); } CRoomListView *pView = GetRoster(); if (NULL != pView) { pView->ForwardSysChangeMsg(uMsg, wParam, lParam); } switch (uMsg) { case WM_PALETTECHANGED: ::RedrawWindow(GetWindow(), NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); break; } } void CMainUI::OnTimer(HWND hwnd, UINT id) { if (IDT_AUDIO == id) { CAudioControl *pAudioControl = GetAudioControl(); if (NULL != pAudioControl) { DWORD dwLevel; dwLevel = pAudioControl->GetAudioSignalLevel(FALSE /*fSpeaker*/); // This level ranges from 0-100 m_pAudioMic->SetProgressValue(dwLevel); dwLevel = pAudioControl->GetAudioSignalLevel(TRUE /*fSpeaker*/); // This level ranges from 0-100 m_pAudioSpeaker->SetProgressValue(dwLevel); } } } // Get the associated audion control object CAudioControl *CMainUI::GetAudioControl() { return(m_pConfRoom->GetAudioControl()); } static void EnableControl(IGenWindow *pControl, BOOL bEnable) { if (NULL == pControl) { return; } CComPtr spControl = com_cast(pControl); if (spControl) { HWND hwnd = spControl->GetWindow(); if (NULL != hwnd) { EnableWindow(hwnd, bEnable); } } } void CMainUI::OnChangePermissions() { EnableControl(FindControl(ID_TB_NEW_CALL ), m_pConfRoom->IsNewCallAllowed()); EnableControl(FindControl(ID_TB_SHARING ), m_pConfRoom->IsSharingAllowed()); EnableControl(FindControl(ID_TB_CHAT ), m_pConfRoom->IsChatAllowed()); EnableControl(FindControl(ID_TB_NEWWHITEBOARD), m_pConfRoom->IsNewWhiteboardAllowed()); EnableControl(FindControl(ID_TB_FILETRANSFER ), m_pConfRoom->IsFileTransferAllowed()); } void CMainUI::OnCallStarted() { m_bPreviewing = FALSE; UpdateViewState(); UpdatePlayPauseState(); } void CMainUI::OnCallEnded() { m_bPreviewing = TRUE; UpdateViewState(); UpdatePlayPauseState(); } void CMainUI::OnAudioLevelChange(BOOL fSpeaker, DWORD dwVolume) { CProgressTrackbar *pBar = fSpeaker ? m_pAudioSpeaker : m_pAudioMic; if (NULL != pBar) { pBar->SetTrackValue((dwVolume*AudioMax + AudioVolMax/2) / AudioVolMax); } } void CMainUI::OnAudioMuteChange(BOOL fSpeaker, BOOL fMute) { IGenWindow *pButton = FindControl(fSpeaker ? ID_TB_TUNESPEAKER_UNMUTE : ID_TB_TUNEMIC_UNMUTE); if (NULL != pButton) { CComPtr spButton = com_cast(pButton); if (spButton) { UpdateMuteState(fSpeaker, spButton); } } } BOOL CMainUI::GetPlayPauseState() { BOOL bMuted = TRUE; // We're just going to show the state for the "big" window if (IsPreviewing()) { if (NULL != m_pLocalVideo) { bMuted = bMuted && m_pLocalVideo->IsPaused(); } } else { if (NULL != m_pRemoteVideo) { bMuted = bMuted && m_pRemoteVideo->IsPaused(); } } return(bMuted); } void CMainUI::UpdatePlayPauseState() { BOOL bMuted = GetPlayPauseState(); IGenWindow *pButton = FindControl(ID_TB_PLAYPAUSE); if (NULL != pButton) { CComPtr spButton = com_cast(pButton); if (spButton) { spButton->SetCustomState(bMuted ? 0 : 1); spButton->SetTooltip(RES2T(bMuted ? IDS_TT_TB_PLAYPAUSE : IDS_TT_TB_PAUSE)); } } } void CMainUI::TogglePlayPause() { // We're going to apply the current state to both videos BOOL bMute = !GetPlayPauseState(); if (NULL != m_pRemoteVideo) { m_pRemoteVideo->Pause(bMute); } if (NULL != m_pLocalVideo) { m_pLocalVideo->Pause(bMute); } UpdatePlayPauseState(); } void CMainUI::OnChangeParticipant(CParticipant *pPart, NM_MEMBER_NOTIFY uNotify) { CRoomListView *pView = GetRoster(); if (NULL != pView) { pView->OnChangeParticipant(pPart, uNotify); } } void CMainUI::OnVideoChannelChanged(NM_CHANNEL_NOTIFY uNotify, INmChannel *pChannel) { // BUGBUG georgep: This really should only go to one or the other, // depending on if it is incoming, but I'm sending to both CVideoWindow *pVideo; pVideo = GetRemoteVideo(); if (NULL != pVideo) { pVideo->OnChannelChanged(uNotify, pChannel); } pVideo = GetLocalVideo(); if (NULL != pVideo) { pVideo->OnChannelChanged(uNotify, pChannel); } } void CMainUI::StateChange(CVideoWindow *pVideo, NM_VIDEO_STATE uState) { UpdatePlayPauseState(); } CFrame *CMainUI::s_pVideoFrame = NULL; class CVideoFrame : public CFrame { protected: virtual LRESULT ProcessMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: { RECT rc; ::GetWindowRect(hwnd, &rc); RegEntry reVideo( VIDEO_LOCAL_KEY, HKEY_CURRENT_USER ); reVideo.SetValue(REGVAL_VIDEO_XPOS, rc.left); reVideo.SetValue(REGVAL_VIDEO_YPOS, rc.top); break; } } return(CFrame::ProcessMessage(hwnd, uMsg, wParam, lParam)); } } ; BOOL CMainUI::NewVideoWindow(CConfRoom *pConfRoom) { if (NULL == s_pVideoFrame) { s_pVideoFrame = new CVideoFrame(); if (NULL == s_pVideoFrame) { // Could not initialize return(FALSE); } } HWND hwnd = s_pVideoFrame->GetWindow(); if (NULL != hwnd) { return(s_pVideoFrame->SetForeground()); } TCHAR szTitle[256]; LoadString(::GetInstanceHandle(), IDS_MYVIDEO, szTitle, ARRAY_ELEMENTS(szTitle)); HICON hiBig = LoadIcon(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_CONFROOM)); if (!s_pVideoFrame->Create( NULL, // Window owner szTitle, // Window name (WS_OVERLAPPEDWINDOW&~(WS_THICKFRAME|WS_MAXIMIZEBOX)), // Window style 0, // Extended window style 0, // Window pos: x 0, // Window pos: y 500, // Window size: width 500, // Window size: height _Module.GetModuleInstance(), // The hInstance to create the window on hiBig, // The icon for the window NULL // Window menu )) { return(FALSE); } BOOL bRet = FALSE; CMainUI *pMainUI = new CMainUI(); if (NULL != pMainUI) { if (pMainUI->Create(s_pVideoFrame->GetWindow(), pConfRoom, CreatePreviewOnly)) { // Make sure it is the right size before showing the window s_pVideoFrame->Resize(); RegEntry reVideo( VIDEO_LOCAL_KEY, HKEY_CURRENT_USER ); int x = reVideo.GetNumber( REGVAL_VIDEO_XPOS, 0x7fff ); int y = reVideo.GetNumber( REGVAL_VIDEO_YPOS, 0x7fff ); s_pVideoFrame->MoveEnsureVisible(x, y); bRet = s_pVideoFrame->SetForeground(); } pMainUI->Release(); } if (!bRet) { DestroyWindow(s_pVideoFrame->GetWindow()); } return(bRet); } void CMainUI::CleanUpVideoWindow() { if (NULL != s_pVideoFrame) { HWND hwnd = s_pVideoFrame->GetWindow(); if (NULL != hwnd) { DestroyWindow(hwnd); } s_pVideoFrame->Release(); s_pVideoFrame = NULL; } } CRoomListView *CMainUI::GetRoster() const { return(NULL == m_pRoster ? NULL : m_pRoster->GetRoster()); }