Files
Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
Jason Alborough aea6942a1f Update to support Cisco Codec External Sources using Essentials Room logic.
Adds new interface for Codecs IHasExternalSourceSwitching
Adds ability to set and clear External Sources in Cisco Spark device class
Adds ability to send sources from the source list to the Cisco Spark in the "EssentialsHuddleVtc1Room" room
[ ] still needs parsing when source is selected on the Cisco touch 10
2020-08-14 15:51:37 -04:00

1460 lines
55 KiB
C#

using System;
using System.Linq;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class EssentialsHuddleVtc1PanelAvFunctionsDriver : PanelDriverBase, IAVWithVCDriver
{
CrestronTouchpanelPropertiesConfig Config;
public enum UiDisplayMode
{
Presentation, AudioSetup, Call, Start
}
public uint StartPageVisibleJoin { get; private set; }
/// <summary>
/// Whether volume ramping from this panel will show the volume
/// gauge popup.
/// </summary>
public bool ShowVolumeGauge { get; set; }
/// <summary>
///
/// </summary>
public uint PowerOffTimeout { get; set; }
/// <summary>
///
/// </summary>
public string DefaultRoomKey { get; set; }
/// <summary>
///
/// </summary>
public EssentialsHuddleVtc1Room CurrentRoom
{
get { return _CurrentRoom; }
set
{
SetCurrentRoom(value);
}
}
EssentialsHuddleVtc1Room _CurrentRoom;
/// <summary>
/// For hitting feedbacks
/// </summary>
BoolInputSig CallButtonSig;
BoolInputSig ShareButtonSig;
BoolInputSig EndMeetingButtonSig;
BoolFeedback CallSharingInfoVisibleFeedback;
/// <summary>
/// The parent driver for this
/// </summary>
PanelDriverBase Parent;
/// <summary>
/// All children attached to this driver. For hiding and showing as a group.
/// </summary>
List<PanelDriverBase> ChildDrivers = new List<PanelDriverBase>();
List<BoolInputSig> CurrentDisplayModeSigsInUse = new List<BoolInputSig>();
//// Important smart objects
/// <summary>
/// Smart Object 3200
/// </summary>
SubpageReferenceList SourceStagingSrl;
/// <summary>
/// Smart Object 15022
/// </summary>
SubpageReferenceList ActivityFooterSrl;
/// <summary>
///
/// </summary>
public SubpageReferenceList MeetingOrContactMethodModalSrl { get; set; }
/// <summary>
/// The list of buttons on the header. Managed with visibility only
/// </summary>
//SmartObjectHeaderButtonList HeaderButtonsList;
/// <summary>
/// The AV page mangagers that have been used, to keep them alive for later
/// </summary>
Dictionary<object, PageManager> PageManagers = new Dictionary<object, PageManager>();
/// <summary>
/// Current page manager running for a source
/// </summary>
PageManager CurrentSourcePageManager;
/// <summary>
/// Will auto-timeout a power off
/// </summary>
CTimer PowerOffTimer;
/// <summary>
///
/// </summary>
ModalDialog PowerDownModal;
/// <summary>
///
/// </summary>
//ModalDialog WarmingCoolingModal;
/// <summary>
/// Represents
/// </summary>
public JoinedSigInterlock PopupInterlock { get; private set; }
/// <summary>
/// Interlock for various source, camera, call control bars. The bar above the activity footer. This is also
/// used to show start page
/// </summary>
JoinedSigInterlock StagingBarInterlock;
/// <summary>
/// Interlocks the various call-related subpages
/// </summary>
JoinedSigInterlock CallPagesInterlock;
/// <summary>
/// The Video codec driver
/// </summary>
PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver VCDriver;
/// <summary>
/// The driver for the tech page. Lazy getter for memory usage
/// </summary>
PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver TechDriver
{
get
{
if (_TechDriver == null)
_TechDriver = new PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver(TriList, CurrentRoom.PropertiesConfig.Tech);
return _TechDriver;
}
}
PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver _TechDriver;
/// <summary>
/// Controls timeout of notification ribbon timer
/// </summary>
CTimer RibbonTimer;
/// <summary>
/// The keyboard
/// </summary>
public PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; private set; }
/// <summary>
/// The mode showing. Presentation or call.
/// </summary>
UiDisplayMode CurrentMode = UiDisplayMode.Start;
CTimer NextMeetingTimer;
/// <summary>
/// Tracks the last meeting that was cancelled
/// </summary>
string LastMeetingDismissedId;
/// <summary>
/// Constructor
/// </summary>
public EssentialsHuddleVtc1PanelAvFunctionsDriver(PanelDriverBase parent, CrestronTouchpanelPropertiesConfig config)
: base(parent.TriList)
{
Config = config;
Parent = parent;
PopupInterlock = new JoinedSigInterlock(TriList);
StagingBarInterlock = new JoinedSigInterlock(TriList);
CallPagesInterlock = new JoinedSigInterlock(TriList);
SourceStagingSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.SourceStagingSRL, 3, 3, 3);
ActivityFooterSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.ActivityFooterSRL, 3, 3, 3);
CallButtonSig = ActivityFooterSrl.BoolInputSig(2, 1);
ShareButtonSig = ActivityFooterSrl.BoolInputSig(1, 1);
EndMeetingButtonSig = ActivityFooterSrl.BoolInputSig(3, 1);
MeetingOrContactMethodModalSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.MeetingListSRL, 3, 3, 5);
// buttons are added in SetCurrentRoom
//HeaderButtonsList = new SmartObjectHeaderButtonList(TriList.SmartObjects[UISmartObjectJoin.HeaderButtonList]);
SetupActivityFooterWhenRoomOff();
ShowVolumeGauge = true;
Keyboard = new PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController(TriList);
}
/// <summary>
/// Add a video codec driver to this
/// </summary>
/// <param name="vcd"></param>
public void SetVideoCodecDriver(PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver vcd)
{
VCDriver = vcd;
}
/// <summary>
///
/// </summary>
public override void Show()
{
if (CurrentRoom == null)
{
Debug.Console(1, "ERROR: AVUIFunctionsDriver, Cannot show. No room assigned");
return;
}
var roomConf = CurrentRoom.PropertiesConfig;
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
{
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
{
if (CurrentRoom.IsMobileControlEnabled)
{
Debug.Console(1, "Showing Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoMCPageVisible);
}
else
{
Debug.Console(1, "Showing Non Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoPageVisible);
}
});
}
else if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Verbose)
{
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
{
if (CurrentRoom.IsMobileControlEnabled)
{
Debug.Console(1, "Showing Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoMCPageVisible);
}
else
{
Debug.Console(1, "Showing Non Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoPageVisible);
}
});
}
TriList.SetBool(UIBoolJoin.DateAndTimeVisible, Config.ShowDate && Config.ShowTime);
TriList.SetBool(UIBoolJoin.DateOnlyVisible, Config.ShowDate && !Config.ShowTime);
TriList.SetBool(UIBoolJoin.TimeOnlyVisible, !Config.ShowDate && Config.ShowTime);
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
TriList.SetBool(UIBoolJoin.ActivityFooterVisible, true);
// Privacy mute button
TriList.SetSigFalseAction(UIBoolJoin.Volume1SpeechMutePressAndFB, CurrentRoom.PrivacyModeToggle);
CurrentRoom.PrivacyModeIsOnFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.Volume1SpeechMutePressAndFB]);
// Default to showing rooms/sources now.
if (CurrentRoom.OnFeedback.BoolValue)
{
TriList.SetBool(UIBoolJoin.TapToBeginVisible, false);
SetupActivityFooterWhenRoomOn();
}
else
{
TriList.SetBool(StartPageVisibleJoin, true);
TriList.SetBool(UIBoolJoin.TapToBeginVisible, true);
SetupActivityFooterWhenRoomOff();
}
ShowCurrentDisplayModeSigsInUse();
// *** Header Buttons ***
// Generic "close" button for popup modals
TriList.SetSigFalseAction(UIBoolJoin.InterlockedModalClosePress, PopupInterlock.HideAndClear);
// Volume related things
TriList.SetSigFalseAction(UIBoolJoin.VolumeDefaultPress, () => CurrentRoom.SetDefaultLevels());
TriList.SetString(UIStringJoin.AdvancedVolumeSlider1Text, "Room");
//if (TriList is CrestronApp)
// TriList.BooleanInput[UIBoolJoin.GearButtonVisible].BoolValue = false;
//else
// TriList.BooleanInput[UIBoolJoin.GearButtonVisible].BoolValue = true;
// power-related functions
// Note: some of these are not directly-related to the huddle space UI, but are held over
// in case
TriList.SetSigFalseAction(UIBoolJoin.ShowPowerOffPress, EndMeetingPress);
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower)
(CurrentRoom.DefaultDisplay as IPower).PowerToggle();
});
SetupNextMeetingTimer();
base.Show();
}
/// <summary>
/// Allows PopupInterlock to be toggled if the calls list is already visible, or if the codec is in a call
/// </summary>
public void ShowActiveCallsList()
{
TriList.SetBool(UIBoolJoin.CallEndAllConfirmVisible, true);
if(PopupInterlock.CurrentJoin == UIBoolJoin.HeaderActiveCallsListVisible)
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible);
else
{
if((CurrentRoom.ScheduleSource as VideoCodecBase).IsInCall)
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible);
}
}
/// <summary>
///
/// </summary>
void ShowLogo()
{
if (CurrentRoom.LogoUrlLightBkgnd == null)
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, true);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, false);
}
else
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, false);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, true);
TriList.SetString(UIStringJoin.LogoUrlLightBkgnd, _CurrentRoom.LogoUrlLightBkgnd);
TriList.SetString(UIStringJoin.LogoUrlDarkBkgnd, _CurrentRoom.LogoUrlDarkBkgnd);
}
}
/// <summary>
///
/// </summary>
void HideLogo()
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, false);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, false);
}
/// <summary>
///
/// </summary>
public override void Hide()
{
HideAndClearCurrentDisplayModeSigsInUse();
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, false);
TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = false;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
if (NextMeetingTimer != null)
NextMeetingTimer.Stop();
HideNextMeetingPopup();
base.Hide();
}
/// <summary>
/// Reveals a message on the notification ribbon until cleared
/// </summary>
/// <param name="message">Text to display</param>
/// <param name="timeout">Time in ms to display. 0 to keep on screen</param>
public void ShowNotificationRibbon(string message, int timeout)
{
TriList.SetString(UIStringJoin.NotificationRibbonText, message);
TriList.SetBool(UIBoolJoin.NotificationRibbonVisible, true);
if (timeout > 0)
{
if (RibbonTimer != null)
RibbonTimer.Stop();
RibbonTimer = new CTimer(o => {
TriList.SetBool(UIBoolJoin.NotificationRibbonVisible, false);
RibbonTimer = null;
}, timeout);
}
}
/// <summary>
/// Hides the notification ribbon
/// </summary>
public void HideNotificationRibbon()
{
TriList.SetBool(UIBoolJoin.NotificationRibbonVisible, false);
if (RibbonTimer != null)
{
RibbonTimer.Stop();
RibbonTimer = null;
}
}
void SetupNextMeetingTimer()
{
var ss = CurrentRoom.ScheduleSource;
if (ss != null)
{
NextMeetingTimer = new CTimer(o => ShowNextMeetingTimerCallback(), null, 0, 60000);
}
}
/// <summary>
///
/// </summary>
void ShowNextMeetingTimerCallback()
{
// Every 60 seconds, refresh the calendar
RefreshMeetingsList();
// check meetings list for the closest, joinable meeting
var ss = CurrentRoom.ScheduleSource;
var meetings = ss.CodecSchedule.Meetings;
if (meetings.Count > 0)
{
// If the room is off pester the user
// If the room is on, and the meeting is joinable
// and the LastMeetingDismissed != this meeting
var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId);
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : "");
var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue
&& lastMeetingDismissed == meeting)
{
return;
}
LastMeetingDismissedId = null;
// Clear the popup when we run out of meetings
if (meeting == null)
{
HideNextMeetingPopup();
}
else
{
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting");
TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToShortTimeString());
TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToShortTimeString());
TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title);
TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer);
TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () =>
{
HideNextMeetingPopup();
PopupInterlock.Hide();
RoomOnAndDialMeeting(meeting);
});
TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule");
TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () =>
{
HideNextMeetingPopup();
//CalendarPress();
RefreshMeetingsList();
PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible);
});
var indexOfNext = meetings.IndexOf(meeting) + 1;
// indexOf = 3, 4 meetings :
if (indexOfNext < meetings.Count)
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText,
meetings[indexOfNext].StartTime.ToShortTimeString());
else
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () =>
{
// Mark the meeting to not re-harass the user
if(CurrentRoom.OnFeedback.BoolValue)
LastMeetingDismissedId = meeting.Id;
HideNextMeetingPopup();
});
TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true);
}
}
}
/// <summary>
///
/// </summary>
void HideNextMeetingPopup()
{
TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, false);
}
/// <summary>
/// Calendar should only be visible when it's supposed to
/// </summary>
public void CalendarPress()
{
//RefreshMeetingsList(); // List should be up-to-date
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.MeetingsOrContacMethodsListVisible);
}
/// <summary>
/// Dials a meeting after turning on room (if necessary)
/// </summary>
void RoomOnAndDialMeeting(Meeting meeting)
{
Action dialAction = () =>
{
var d = CurrentRoom.ScheduleSource as VideoCodecBase;
if (d != null)
{
d.Dial(meeting);
LastMeetingDismissedId = meeting.Id; // To prevent prompts for already-joined call
}
};
if (CurrentRoom.OnFeedback.BoolValue)
dialAction();
else
{
// Rig a one-time handler to catch when the room is warmed and then dial call
EventHandler<FeedbackEventArgs> oneTimeHandler = null;
oneTimeHandler = (o, a) =>
{
if (!CurrentRoom.IsWarmingUpFeedback.BoolValue)
{
CurrentRoom.IsWarmingUpFeedback.OutputChange -= oneTimeHandler;
dialAction();
}
};
CurrentRoom.IsWarmingUpFeedback.OutputChange += oneTimeHandler;
ActivityCallButtonPressed();
}
}
/// <summary>
/// Reveals the tech page and puts away anything that's in the way.
/// </summary>
public void ShowTech()
{
PopupInterlock.HideAndClear();
TechDriver.Show();
}
/// <summary>
/// When the room is off, set the footer SRL
/// </summary>
void SetupActivityFooterWhenRoomOff()
{
ActivityFooterSrl.Clear();
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 0,
b => { if (!b) ActivityShareButtonPressed(); }));
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl, 3,
b => { if (!b) ActivityCallButtonPressed(); }));
ActivityFooterSrl.Count = 2;
TriList.SetUshort(UIUshortJoin.PresentationStagingCaretMode, 1); // right one slot
TriList.SetUshort(UIUshortJoin.CallStagingCaretMode, 5); // left one slot
}
/// <summary>
/// Sets up the footer SRL for when the room is on
/// </summary>
void SetupActivityFooterWhenRoomOn()
{
ActivityFooterSrl.Clear();
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 0,
b => { if (!b) ActivityShareButtonPressed(); }));
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl, 3,
b => { if (!b) ActivityCallButtonPressed(); }));
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(3, ActivityFooterSrl, 4,
b => { if (!b) EndMeetingPress(); }));
ActivityFooterSrl.Count = 3;
TriList.SetUshort(UIUshortJoin.PresentationStagingCaretMode, 2); // center
TriList.SetUshort(UIUshortJoin.CallStagingCaretMode, 0); // left -2
}
/// <summary>
/// Single point call for setting the feedbacks on the activity buttons
/// </summary>
void SetActivityFooterFeedbacks()
{
CallButtonSig.BoolValue = CurrentMode == UiDisplayMode.Call
&& CurrentRoom.ShutdownType == eShutdownType.None;
ShareButtonSig.BoolValue = CurrentMode == UiDisplayMode.Presentation
&& CurrentRoom.ShutdownType == eShutdownType.None;
EndMeetingButtonSig.BoolValue = CurrentRoom.ShutdownType != eShutdownType.None;
}
/// <summary>
///
/// </summary>
public void ActivityCallButtonPressed()
{
if (VCDriver.IsVisible)
return;
HideLogo();
HideNextMeetingPopup();
TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
if (CurrentSourcePageManager != null)
CurrentSourcePageManager.Hide();
PowerOnFromCall();
CurrentMode = UiDisplayMode.Call;
SetActivityFooterFeedbacks();
VCDriver.Show();
}
/// <summary>
/// Attached to activity list share button
/// </summary>
void ActivityShareButtonPressed()
{
SetupSourceList();
if (VCDriver.IsVisible)
VCDriver.Hide();
HideNextMeetingPopup();
TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.CallStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, true);
// Run default source when room is off and share is pressed
if (!CurrentRoom.OnFeedback.BoolValue)
{
if (!CurrentRoom.OnFeedback.BoolValue)
{
// If there's no default, show UI elements
if (!CurrentRoom.RunDefaultPresentRoute())
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
}
}
else // room is on show what's active or select a source if nothing is yet active
{
if(CurrentRoom.CurrentSourceInfo == null || CurrentRoom.CurrentSourceInfoKey == CurrentRoom.DefaultCodecRouteString)
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
else if (CurrentSourcePageManager != null)
CurrentSourcePageManager.Show();
}
CurrentMode = UiDisplayMode.Presentation;
SetupSourceList();
SetActivityFooterFeedbacks();
}
/// <summary>
/// Powers up the system to the codec route, if not already on.
/// </summary>
void PowerOnFromCall()
{
if (!CurrentRoom.OnFeedback.BoolValue)
{
CurrentRoom.RunDefaultCallRoute();
}
}
/// <summary>
/// Shows all sigs that are in CurrentDisplayModeSigsInUse
/// </summary>
void ShowCurrentDisplayModeSigsInUse()
{
foreach (var sig in CurrentDisplayModeSigsInUse)
sig.BoolValue = true;
}
/// <summary>
/// Hides all CurrentDisplayModeSigsInUse sigs and clears the array
/// </summary>
void HideAndClearCurrentDisplayModeSigsInUse()
{
foreach (var sig in CurrentDisplayModeSigsInUse)
sig.BoolValue = false;
CurrentDisplayModeSigsInUse.Clear();
}
/// <summary>
/// Loads the appropriate Sigs into CurrentDisplayModeSigsInUse and shows them
/// </summary>
void ShowCurrentSource()
{
if (CurrentRoom.CurrentSourceInfo == null)
return;
if (CurrentRoom.CurrentSourceInfo.SourceDevice == null)
{
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
return;
}
var uiDev = CurrentRoom.CurrentSourceInfo.SourceDevice as IUiDisplayInfo;
PageManager pm = null;
// If we need a page manager, get an appropriate one
if (uiDev != null)
{
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
// Got an existing page manager, get it
if (PageManagers.ContainsKey(uiDev))
pm = PageManagers[uiDev];
// Otherwise make an apporiate one
else if (uiDev is ISetTopBoxControls)
pm = new SetTopBoxThreePanelPageManager(uiDev as ISetTopBoxControls, TriList);
else if (uiDev is IDiscPlayerControls)
pm = new DiscPlayerMediumPageManager(uiDev as IDiscPlayerControls, TriList);
else
pm = new DefaultPageManager(uiDev, TriList);
PageManagers[uiDev] = pm;
CurrentSourcePageManager = pm;
pm.Show();
}
}
/// <summary>
/// Called from button presses on source, where We can assume we want
/// to change to the proper screen.
/// </summary>
/// <param name="key">The key name of the route to run</param>
void UiSelectSource(string key)
{
// Run the route and when it calls back, show the source
CurrentRoom.RunRouteAction(key, new Action(() => { }));
}
/// <summary>
///
/// </summary>
public void EndMeetingPress()
{
if (!CurrentRoom.OnFeedback.BoolValue
|| CurrentRoom.ShutdownPromptTimer.IsRunningFeedback.BoolValue)
return;
CurrentRoom.StartShutdown(eShutdownType.Manual);
}
/// <summary>
/// Puts away modals and things that might be up when call comes in
/// </summary>
public void PrepareForCodecIncomingCall()
{
if (PowerDownModal != null && PowerDownModal.ModalIsVisible)
PowerDownModal.CancelDialog();
PopupInterlock.Hide();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ShutdownPromptTimer_HasStarted(object sender, EventArgs e)
{
// Do we need to check where the UI is? No?
var timer = CurrentRoom.ShutdownPromptTimer;
SetActivityFooterFeedbacks();
if (CurrentRoom.ShutdownType == eShutdownType.Manual || CurrentRoom.ShutdownType == eShutdownType.Vacancy)
{
PowerDownModal = new ModalDialog(TriList);
var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
// Attach timer things to modal
CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange += ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange += ShutdownPromptTimer_PercentFeedback_OutputChange;
// respond to offs by cancelling dialog
var onFb = CurrentRoom.OnFeedback;
EventHandler<FeedbackEventArgs> offHandler = null;
offHandler = (o, a) =>
{
if (!onFb.BoolValue)
{
PowerDownModal.HideDialog();
SetActivityFooterFeedbacks();
onFb.OutputChange -= offHandler;
}
};
onFb.OutputChange += offHandler;
PowerDownModal.PresentModalDialog(2, "End Meeting", "Power", message, "Cancel", "End Meeting Now", true, true,
but =>
{
if (but != 2) // any button except for End cancels
timer.Cancel();
else
timer.Finish();
});
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
SetActivityFooterFeedbacks();
CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange -= ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange -= ShutdownPromptTimer_PercentFeedback_OutputChange;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ShutdownPromptTimer_WasCancelled(object sender, EventArgs e)
{
if (PowerDownModal != null)
PowerDownModal.HideDialog();
SetActivityFooterFeedbacks();
CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange += ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange -= ShutdownPromptTimer_PercentFeedback_OutputChange;
}
/// <summary>
/// Event handler for countdown timer on power off modal
/// </summary>
void ShutdownPromptTimer_TimeRemainingFeedback_OutputChange(object sender, EventArgs e)
{
var message = string.Format("Meeting will end in {0} seconds", (sender as StringFeedback).StringValue);
TriList.StringInput[ModalDialog.MessageTextJoin].StringValue = message;
}
/// <summary>
/// Event handler for percentage on power off countdown
/// </summary>
void ShutdownPromptTimer_PercentFeedback_OutputChange(object sender, EventArgs e)
{
var value = (ushort)((sender as IntFeedback).UShortValue * 65535 / 100);
TriList.UShortInput[ModalDialog.TimerGaugeJoin].UShortValue = value;
}
/// <summary>
///
/// </summary>
void CancelPowerOffTimer()
{
if (PowerOffTimer != null)
{
PowerOffTimer.Stop();
PowerOffTimer = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
public void VolumeUpPress(bool state)
{
if (CurrentRoom.CurrentVolumeControls != null)
CurrentRoom.CurrentVolumeControls.VolumeUp(state);
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
public void VolumeDownPress(bool state)
{
if (CurrentRoom.CurrentVolumeControls != null)
CurrentRoom.CurrentVolumeControls.VolumeDown(state);
}
/// <summary>
/// Helper for property setter. Sets the panel to the given room, latching up all functionality
/// </summary>
void RefreshCurrentRoom(EssentialsHuddleVtc1Room room)
{
if (_CurrentRoom != null)
{
// Disconnect current room
_CurrentRoom.CurrentVolumeDeviceChange -= this.CurrentRoom_CurrentAudioDeviceChange;
ClearAudioDeviceConnections();
_CurrentRoom.CurrentSourceChange -= this.CurrentRoom_SourceInfoChange;
DisconnectSource(_CurrentRoom.CurrentSourceInfo);
_CurrentRoom.ShutdownPromptTimer.HasStarted -= ShutdownPromptTimer_HasStarted;
_CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
_CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
_CurrentRoom.OnFeedback.OutputChange -= CurrentRoom_OnFeedback_OutputChange;
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDownFeedback_OutputChange;
_CurrentRoom.InCallFeedback.OutputChange -= CurrentRoom_InCallFeedback_OutputChange;
}
_CurrentRoom = room;
if (_CurrentRoom != null)
{
// get the source list config and set up the source list
SetupSourceList();
// Name and logo
TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _CurrentRoom.Name;
ShowLogo();
// Shutdown timer
_CurrentRoom.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
_CurrentRoom.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
_CurrentRoom.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
// Link up all the change events from the room
_CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
CurrentRoom_SyncOnFeedback();
_CurrentRoom.IsWarmingUpFeedback.OutputChange += CurrentRoom_IsWarmingFeedback_OutputChange;
_CurrentRoom.IsCoolingDownFeedback.OutputChange += CurrentRoom_IsCoolingDownFeedback_OutputChange;
_CurrentRoom.InCallFeedback.OutputChange += CurrentRoom_InCallFeedback_OutputChange;
_CurrentRoom.CurrentVolumeDeviceChange += CurrentRoom_CurrentAudioDeviceChange;
RefreshAudioDeviceConnections();
_CurrentRoom.CurrentSourceChange += CurrentRoom_SourceInfoChange;
RefreshSourceInfo();
if (_CurrentRoom.VideoCodec is IHasScheduleAwareness)
{
(_CurrentRoom.VideoCodec as IHasScheduleAwareness).CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged;
}
CallSharingInfoVisibleFeedback = new BoolFeedback(() => _CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue);
_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange;
CallSharingInfoVisibleFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.CallSharedSourceInfoVisible]);
SetActiveCallListSharingContentStatus();
if (_CurrentRoom != null)
_CurrentRoom.CurrentSourceChange += new SourceInfoChangeHandler(CurrentRoom_CurrentSingleSourceChange);
TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, () => _CurrentRoom.RunRouteAction("codecOsd", _CurrentRoom.SourceListKey));
(Parent as EssentialsPanelMainInterfaceDriver).HeaderDriver.SetupHeaderButtons(this, CurrentRoom);
}
else
{
// Clear sigs that need to be
TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = "Select a room";
}
}
void SetCurrentRoom(EssentialsHuddleVtc1Room room)
{
if (_CurrentRoom == room) return;
// Disconnect current (probably never called)
if(_CurrentRoom != null)
_CurrentRoom.ConfigChanged -= room_ConfigChanged;
room.ConfigChanged -= room_ConfigChanged;
room.ConfigChanged += room_ConfigChanged;
if (room.IsMobileControlEnabled)
{
StartPageVisibleJoin = UIBoolJoin.StartMCPageVisible;
UpdateMCJoins(room);
if (_CurrentRoom != null)
_CurrentRoom.MobileControlRoomBridge.UserCodeChanged -= MobileControlRoomBridge_UserCodeChanged;
room.MobileControlRoomBridge.UserCodeChanged -= MobileControlRoomBridge_UserCodeChanged;
room.MobileControlRoomBridge.UserCodeChanged += MobileControlRoomBridge_UserCodeChanged;
}
else
{
StartPageVisibleJoin = UIBoolJoin.StartPageVisible;
}
RefreshCurrentRoom(room);
}
void MobileControlRoomBridge_UserCodeChanged(object sender, EventArgs e)
{
UpdateMCJoins(_CurrentRoom);
}
void UpdateMCJoins(EssentialsHuddleVtc1Room room)
{
TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl);
TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl);
TriList.SetString(UIStringJoin.RoomUserCode, room.MobileControlRoomBridge.UserCode);
}
/// <summary>
/// Fires when room config of current room has changed. Meant to refresh room values to propegate any updates to UI
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void room_ConfigChanged(object sender, EventArgs e)
{
RefreshCurrentRoom(_CurrentRoom);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CurrentRoom_InCallFeedback_OutputChange(object sender, EventArgs e)
{
var inCall = CurrentRoom.InCallFeedback.BoolValue;
if (inCall)
{
// Check if transitioning to in call - and non-sharable source is in use
if (CurrentRoom.CurrentSourceInfo != null && CurrentRoom.CurrentSourceInfo.DisableCodecSharing)
{
Debug.Console(1, CurrentRoom, "Transitioning to in-call, cancelling non-sharable source");
CurrentRoom.RunRouteAction("codecOsd", CurrentRoom.SourceListKey);
}
}
SetupSourceList();
}
/// <summary>
///
/// </summary>
void SetupSourceList()
{
var inCall = CurrentRoom.InCallFeedback.BoolValue;
var config = ConfigReader.ConfigObject.SourceLists;
if (config.ContainsKey(_CurrentRoom.SourceListKey))
{
var srcList = config[_CurrentRoom.SourceListKey].OrderBy(kv => kv.Value.Order);
// Setup sources list
SourceStagingSrl.Clear();
uint i = 1; // counter for UI list
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
Debug.Console(1, "**** {0}, {1}, {2}, {3}, {4}", srcConfig.PreferredName, srcConfig.IncludeInSourceList,
srcConfig.DisableCodecSharing, inCall, this.CurrentMode);
// Skip sources marked as not included, and filter list of non-sharable sources when in call
// or on share screen
if (!srcConfig.IncludeInSourceList || (inCall && srcConfig.DisableCodecSharing)
|| this.CurrentMode == UiDisplayMode.Call && srcConfig.DisableCodecSharing)
{
Debug.Console(1, "Skipping {0}", srcConfig.PreferredName);
continue;
}
var routeKey = kvp.Key;
var item = new SubpageReferenceListSourceItem(i++, SourceStagingSrl, srcConfig,
b => { if (!b) UiSelectSource(routeKey); });
SourceStagingSrl.AddItem(item); // add to the SRL
item.RegisterForSourceChange(_CurrentRoom);
Debug.Console(1, "**** KEY {0}", kvp.Key);
}
SourceStagingSrl.Count = (ushort)(i - 1);
}
}
/// <summary>
/// If the schedule changes, this event will fire
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CodecSchedule_MeetingsListHasChanged(object sender, EventArgs e)
{
RefreshMeetingsList();
}
/// <summary>
/// Updates the current shared source label on the call list when the source changes
/// </summary>
/// <param name="room"></param>
/// <param name="info"></param>
/// <param name="type"></param>
void CurrentRoom_CurrentSingleSourceChange(SourceListItem info, ChangeType type)
{
if (_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && _CurrentRoom.CurrentSourceInfo != null)
TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = _CurrentRoom.CurrentSourceInfo.PreferredName;
}
/// <summary>
/// Fires when the sharing source feedback of the codec changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void SharingContentIsOnFeedback_OutputChange(object sender, EventArgs e)
{
SetActiveCallListSharingContentStatus();
}
/// <summary>
/// Sets the values for the text and button visibilty for the active call list source sharing info
/// </summary>
void SetActiveCallListSharingContentStatus()
{
CallSharingInfoVisibleFeedback.FireUpdate();
string callListSharedSourceLabel;
if (_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && _CurrentRoom.CurrentSourceInfo != null)
{
Debug.Console(0, "*#* CurrentRoom.CurrentSourceInfo = {0}",
_CurrentRoom.CurrentSourceInfo != null ? _CurrentRoom.CurrentSourceInfo.SourceKey : "Nada!");
callListSharedSourceLabel = _CurrentRoom.CurrentSourceInfo.PreferredName;
}
else
callListSharedSourceLabel = "None";
TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = callListSharedSourceLabel;
}
/// <summary>
///
/// </summary>
void RefreshMeetingsList()
{
// See if this is helpful or if the callback response in the codec class maybe doesn't come it time?
// Let's build list from event
// CurrentRoom.ScheduleSource.GetSchedule();
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar");
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Today's Meetings");
ushort i = 0;
foreach (var m in CurrentRoom.ScheduleSource.CodecSchedule.Meetings)
{
i++;
MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToShortTimeString();
MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToShortTimeString();
MeetingOrContactMethodModalSrl.StringInputSig(i, 3).StringValue = m.Title;
MeetingOrContactMethodModalSrl.StringInputSig(i, 4).StringValue = string.Format("<br>{0}",m.Organizer);
MeetingOrContactMethodModalSrl.StringInputSig(i, 5).StringValue = "Join";
MeetingOrContactMethodModalSrl.BoolInputSig(i, 2).BoolValue = m.Joinable;
var mm = m; // lambda scope
MeetingOrContactMethodModalSrl.GetBoolFeedbackSig(i, 1).SetSigFalseAction(() =>
{
PopupInterlock.Hide();
ActivityCallButtonPressed();
var d = CurrentRoom.ScheduleSource as VideoCodecBase;
if (d != null)
RoomOnAndDialMeeting(mm);
});
}
MeetingOrContactMethodModalSrl.Count = i;
if (i == 0) // Show item indicating no meetings are booked for rest of day
{
MeetingOrContactMethodModalSrl.Count = 1;
MeetingOrContactMethodModalSrl.StringInputSig(1, 1).StringValue = string.Empty;
MeetingOrContactMethodModalSrl.StringInputSig(1, 2).StringValue = string.Empty;
MeetingOrContactMethodModalSrl.StringInputSig(1, 3).StringValue = "No Meetings are booked for the remainder of the day.";
MeetingOrContactMethodModalSrl.StringInputSig(1, 4).StringValue = string.Empty;
MeetingOrContactMethodModalSrl.StringInputSig(1, 5).StringValue = string.Empty;
}
}
/// <summary>
/// For room on/off changes
/// </summary>
void CurrentRoom_OnFeedback_OutputChange(object sender, EventArgs e)
{
CurrentRoom_SyncOnFeedback();
}
/// <summary>
///
/// </summary>
void CurrentRoom_SyncOnFeedback()
{
var value = _CurrentRoom.OnFeedback.BoolValue;
TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value;
if (value) //ON
{
SetupActivityFooterWhenRoomOn();
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = true;
}
else
{
CurrentMode = UiDisplayMode.Start;
if (VCDriver.IsVisible)
VCDriver.Hide();
SetupActivityFooterWhenRoomOff();
ShowLogo();
SetActivityFooterFeedbacks();
TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
// Clear this so that the pesky meeting warning can resurface every minute when off
LastMeetingDismissedId = null;
}
}
/// <summary>
///
/// </summary>
void CurrentRoom_IsWarmingFeedback_OutputChange(object sender, EventArgs e)
{
if (CurrentRoom.IsWarmingUpFeedback.BoolValue)
{
ShowNotificationRibbon("Room is powering on. Please wait...", 0);
}
else
{
ShowNotificationRibbon("Room is powered on. Welcome.", 2000);
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CurrentRoom_IsCoolingDownFeedback_OutputChange(object sender, EventArgs e)
{
if (CurrentRoom.IsCoolingDownFeedback.BoolValue)
{
ShowNotificationRibbon("Room is powering off. Please wait.", 0);
}
else
{
HideNotificationRibbon();
}
}
/// <summary>
/// Hides source for provided source info
/// </summary>
/// <param name="previousInfo"></param>
void DisconnectSource(SourceListItem previousInfo)
{
if (previousInfo == null) return;
// Hide whatever is showing
if (IsVisible)
{
if (CurrentSourcePageManager != null)
{
CurrentSourcePageManager.Hide();
CurrentSourcePageManager = null;
}
}
if (previousInfo == null) return;
var previousDev = previousInfo.SourceDevice;
// device type interfaces
if (previousDev is ISetTopBoxControls)
(previousDev as ISetTopBoxControls).UnlinkButtons(TriList);
// common interfaces
if (previousDev is IChannel)
(previousDev as IChannel).UnlinkButtons(TriList);
if (previousDev is IColor)
(previousDev as IColor).UnlinkButtons(TriList);
if (previousDev is IDPad)
(previousDev as IDPad).UnlinkButtons(TriList);
if (previousDev is IDvr)
(previousDev as IDvr).UnlinkButtons(TriList);
if (previousDev is INumericKeypad)
(previousDev as INumericKeypad).UnlinkButtons(TriList);
if (previousDev is IPower)
(previousDev as IPower).UnlinkButtons(TriList);
if (previousDev is ITransport)
(previousDev as ITransport).UnlinkButtons(TriList);
}
/// <summary>
/// Refreshes and shows the room's current source
/// </summary>
void RefreshSourceInfo()
{
var routeInfo = CurrentRoom.CurrentSourceInfo;
// This will show off popup too
if (this.IsVisible && !VCDriver.IsVisible)
ShowCurrentSource();
if (routeInfo == null)// || !CurrentRoom.OnFeedback.BoolValue)
{
// Check for power off and insert "Room is off"
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "Room is off";
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Power";
this.Hide();
Parent.Show();
return;
}
else if (routeInfo != null)
{
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = routeInfo.PreferredName;
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = routeInfo.Icon; // defaults to "blank"
}
else // This never gets hit???!!!
{
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "---";
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Blank";
}
// Connect controls
if (routeInfo.SourceDevice != null)
ConnectControlDeviceMethods(routeInfo.SourceDevice);
}
/// <summary>
/// Attach the source to the buttons and things
/// </summary>
void ConnectControlDeviceMethods(Device dev)
{
if (dev is ISetTopBoxControls)
(dev as ISetTopBoxControls).LinkButtons(TriList);
if (dev is IChannel)
(dev as IChannel).LinkButtons(TriList);
if (dev is IColor)
(dev as IColor).LinkButtons(TriList);
if (dev is IDPad)
(dev as IDPad).LinkButtons(TriList);
if (dev is IDvr)
(dev as IDvr).LinkButtons(TriList);
if (dev is INumericKeypad)
(dev as INumericKeypad).LinkButtons(TriList);
if (dev is IPower)
(dev as IPower).LinkButtons(TriList);
if (dev is ITransport)
(dev as ITransport).LinkButtons(TriList);
}
/// <summary>
/// Detaches the buttons and feedback from the room's current audio device
/// </summary>
void ClearAudioDeviceConnections()
{
TriList.ClearBoolSigAction(UIBoolJoin.VolumeUpPress);
TriList.ClearBoolSigAction(UIBoolJoin.VolumeDownPress);
TriList.ClearBoolSigAction(UIBoolJoin.Volume1ProgramMutePressAndFB);
var fDev = CurrentRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
if (fDev != null)
{
TriList.ClearUShortSigAction(UIUshortJoin.VolumeSlider1Value);
fDev.VolumeLevelFeedback.UnlinkInputSig(
TriList.UShortInput[UIUshortJoin.VolumeSlider1Value]);
}
}
/// <summary>
/// Attaches the buttons and feedback to the room's current audio device
/// </summary>
void RefreshAudioDeviceConnections()
{
var dev = CurrentRoom.CurrentVolumeControls;
if (dev != null) // connect buttons
{
TriList.SetBoolSigAction(UIBoolJoin.VolumeUpPress, VolumeUpPress);
TriList.SetBoolSigAction(UIBoolJoin.VolumeDownPress, VolumeDownPress);
TriList.SetSigFalseAction(UIBoolJoin.Volume1ProgramMutePressAndFB, dev.MuteToggle);
}
var fbDev = dev as IBasicVolumeWithFeedback;
if (fbDev == null) // this should catch both IBasicVolume and IBasicVolumeWithFeeback
TriList.UShortInput[UIUshortJoin.VolumeSlider1Value].UShortValue = 0;
else
{
// slider
TriList.SetUShortSigAction(UIUshortJoin.VolumeSlider1Value, fbDev.SetVolume);
// feedbacks
fbDev.MuteFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.Volume1ProgramMutePressAndFB]);
fbDev.VolumeLevelFeedback.LinkInputSig(
TriList.UShortInput[UIUshortJoin.VolumeSlider1Value]);
}
}
/// <summary>
/// Handler for when the room's volume control device changes
/// </summary>
void CurrentRoom_CurrentAudioDeviceChange(object sender, VolumeDeviceChangeEventArgs args)
{
if (args.Type == ChangeType.WillChange)
ClearAudioDeviceConnections();
else // did change
RefreshAudioDeviceConnections();
}
/// <summary>
/// Handles source change
/// </summary>
void CurrentRoom_SourceInfoChange(SourceListItem info, ChangeType change)
{
if (change == ChangeType.WillChange)
DisconnectSource(info);
else
RefreshSourceInfo();
}
}
/// <summary>
/// For hanging off various common AV things that child drivers might need from a parent AV driver
/// </summary>
public interface IAVDriver
{
JoinedSigInterlock PopupInterlock { get; }
void ShowNotificationRibbon(string message, int timeout);
void HideNotificationRibbon();
void ShowTech();
uint StartPageVisibleJoin { get; }
}
/// <summary>
/// For hanging off various common VC things that child drivers might need from a parent AV driver
/// </summary>
public interface IAVWithVCDriver : IAVDriver
{
EssentialsHuddleVtc1Room CurrentRoom { get; }
PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; }
/// <summary>
/// Exposes the ability to switch into call mode
/// </summary>
void ActivityCallButtonPressed();
/// <summary>
/// Allows the codec to trigger the main UI to clear up if call is coming in.
/// </summary>
void PrepareForCodecIncomingCall();
SubpageReferenceList MeetingOrContactMethodModalSrl { get; }
}
}