using System; using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Essentials.Core; using System.Text.RegularExpressions; namespace PepperDash.Essentials.Devices.Common.DSP { public interface IBiampTesiraDspLevelControl : IBasicVolumeWithFeedback { /// /// In BiAmp: Instance Tag, QSC: Named Control, Polycom: /// string ControlPointTag { get; } int Index1 { get; } int Index2 { get; } bool HasMute { get; } bool HasLevel { get; } bool AutomaticUnmuteOnVolumeUp { get; } } public class TesiraForteLevelControl : TesiraForteControlPoint, IBiampTesiraDspLevelControl, IKeyed { bool _IsMuted; ushort _VolumeLevel; public BoolFeedback MuteFeedback { get; private set; } public IntFeedback VolumeLevelFeedback { get; private set; } public bool Enabled { get; set; } public string ControlPointTag { get { return base.InstanceTag; } } /// /// Used for to identify level subscription values /// public string LevelCustomName { get; private set; } /// /// Used for to identify mute subscription values /// public string MuteCustomName { get; private set; } /// /// Minimum fader level /// double MinLevel; /// /// Maximum fader level /// double MaxLevel; /// /// Checks if a valid subscription string has been recieved for all subscriptions /// public bool IsSubsribed { get { bool isSubscribed = false; if (HasMute && MuteIsSubscribed) isSubscribed = true; if (HasLevel && LevelIsSubscribed) isSubscribed = true; return isSubscribed; } } public bool AutomaticUnmuteOnVolumeUp { get; private set; } public bool HasMute { get; private set; } public bool HasLevel { get; private set; } bool MuteIsSubscribed; bool LevelIsSubscribed; //public TesiraForteLevelControl(string label, string id, int index1, int index2, bool hasMute, bool hasLevel, BiampTesiraForteDsp parent) // : base(id, index1, index2, parent) //{ // Initialize(label, hasMute, hasLevel); //} public TesiraForteLevelControl(string key, BiampTesiraForteLevelControlBlockConfig config, BiampTesiraForteDsp parent) : base(config.InstanceTag, config.Index1, config.Index2, parent) { Initialize(key, config.Label, config.HasMute, config.HasLevel); } /// /// Initializes this attribute based on config values and generates subscriptions commands and adds commands to the parent's queue. /// public void Initialize(string key, string label, bool hasMute, bool hasLevel) { Key = string.Format("{0}--{1}", Parent.Key, key); DeviceManager.AddDevice(this); Debug.Console(2, this, "Adding LevelControl '{0}'", Key); this.IsSubscribed = false; MuteFeedback = new BoolFeedback(() => _IsMuted); VolumeLevelFeedback = new IntFeedback(() => _VolumeLevel); HasMute = hasMute; HasLevel = hasLevel; } public void Subscribe() { // Do subscriptions and blah blah // Subscribe to mute if (this.HasMute) { MuteCustomName = string.Format("{0}~mute{1}", this.InstanceTag, this.Index1); SendSubscriptionCommand(MuteCustomName, "mute", 500); } // Subscribe to level if (this.HasLevel) { LevelCustomName = string.Format("{0}~level{1}", this.InstanceTag, this.Index1); SendSubscriptionCommand(LevelCustomName, "level", 250); SendFullCommand("get", "minLevel", null); SendFullCommand("get", "maxLevel", null); } } /// /// Parses the response from the DspBase /// /// /// public void ParseSubscriptionMessage(string customName, string value) { // Check for valid subscription response if (this.HasMute && customName == MuteCustomName) { //if (value.IndexOf("+OK") > -1) //{ // int pointer = value.IndexOf(" +OK"); // MuteIsSubscribed = true; // // Removes the +OK // value = value.Substring(0, value.Length - (value.Length - (pointer - 1))); //} if (value.IndexOf("true") > -1) { _IsMuted = true; MuteIsSubscribed = true; } else if (value.IndexOf("false") > -1) { _IsMuted = false; MuteIsSubscribed = true; } MuteFeedback.FireUpdate(); } else if (this.HasLevel && customName == LevelCustomName) { //if (value.IndexOf("+OK") > -1) //{ // int pointer = value.IndexOf(" +OK"); // LevelIsSubscribed = true; //} var _value = Double.Parse(value); _VolumeLevel = (ushort)Scale(_value, MinLevel, MaxLevel, 0, 65535); LevelIsSubscribed = true; VolumeLevelFeedback.FireUpdate(); } } /// /// Parses a non subscription response /// /// The attribute code of the command /// The message to parse public override void ParseGetMessage(string attributeCode, string message) { try { // Parse an "+OK" message string pattern = @"\+OK ""value"":(.*)"; Match match = Regex.Match(message, pattern); if (match.Success) { string value = match.Groups[1].Value; Debug.Console(1, this, "Response: '{0}' Value: '{1}'", attributeCode, value); if (message.IndexOf("\"value\":") > -1) { switch (attributeCode) { case "minLevel": { MinLevel = Double.Parse(value); Debug.Console(1, this, "MinLevel is '{0}'", MinLevel); break; } case "maxLevel": { MaxLevel = Double.Parse(value); Debug.Console(1, this, "MaxLevel is '{0}'", MaxLevel); break; } default: { Debug.Console(2, "Response does not match expected attribute codes: '{0}'", message); break; } } } } } catch (Exception e) { Debug.Console(2, "Unable to parse message: '{0}'\n{1}", message, e); } } /// /// Turns the mute off /// public void MuteOff() { SendFullCommand("set", "mute", "false"); } /// /// Turns the mute on /// public void MuteOn() { SendFullCommand("set", "mute", "true"); } /// /// Sets the volume to a specified level /// /// public void SetVolume(ushort level) { Debug.Console(1, this, "volume: {0}", level); // Unmute volume if new level is higher than existing if (level > _VolumeLevel && AutomaticUnmuteOnVolumeUp) if(_IsMuted) MuteOff(); double volumeLevel = Scale(level, 0, 65535, MinLevel, MaxLevel); SendFullCommand("set", "level", string.Format("{0:0.000000}", volumeLevel)); } /// /// Toggles mute status /// public void MuteToggle() { SendFullCommand("toggle", "mute", ""); } /// /// Decrements volume level /// /// public void VolumeDown(bool pressRelease) { SendFullCommand("decrement", "level", ""); } /// /// Increments volume level /// /// public void VolumeUp(bool pressRelease) { SendFullCommand("increment", "level", ""); if (AutomaticUnmuteOnVolumeUp) if (!_IsMuted) MuteOff(); } ///// ///// Scales the input from the input range to the output range ///// ///// ///// ///// ///// ///// ///// //int Scale(int input, int inMin, int inMax, int outMin, int outMax) //{ // Debug.Console(1, this, "Scaling (int) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'", input, inMin, inMax, outMin, outMax); // int inputRange = inMax - inMin; // int outputRange = outMax - outMin; // var output = (((input-inMin) * outputRange) / inputRange ) - outMin; // Debug.Console(1, this, "Scaled output '{0}'", output); // return output; //} /// /// Scales the input from the input range to the output range /// /// /// /// /// /// /// double Scale(double input, double inMin, double inMax, double outMin, double outMax) { Debug.Console(1, this, "Scaling (double) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'",input ,inMin ,inMax ,outMin, outMax); double inputRange = inMax - inMin; if (inputRange <= 0) { throw new ArithmeticException(string.Format("Invalid Input Range '{0}' for Scaling. Min '{1}' Max '{2}'.", inputRange, inMin, inMax)); } double outputRange = outMax - outMin; var output = (((input - inMin) * outputRange) / inputRange) + outMin; Debug.Console(1, this, "Scaled output '{0}'", output); return output; } } }