示例#1
0
        /// <summary>
        /// Handles wrapping the session into a higher level object, registering
        /// it in the service and notifying of the event.
        /// </summary>
        /// <param name="session_"></param>
        private void OnSessionCreated(AudioSessionControl session_)
        {
            var session = new AudioSession(session_);

            AppLogging.DebugLog(nameof(OnSessionCreated), session.SessionIdentifier, session.DisplayName, session.Id.ToString());
            RegisterSession(session);
        }
        // Using a template, with a constraint of IMessage allows us to pass the message without boxing reducing garbage generation
        private unsafe void ReadMessage <T>(DateTime now, Command command) where T : unmanaged, IMessage
        {
            int length = 0;

            try
            {
                while (length < sizeof(T))
                {
                    length += m_SerialPort.Read(m_ReadBuffer, length, sizeof(T) - length);
                }

                if (length != sizeof(T))
                {
                    throw new ArgumentException($"Message Length: {length}. Expected Length: {sizeof(T)}.");
                }
            }
            catch (Exception e)
            {
                AppLogging.DebugLogException(nameof(ReadMessage), e);
                Interlocked.Increment(ref m_ErrorCount);
                return;
            }

            T message = new T();

            message.SetBytes(m_ReadBuffer);
            AppLogging.DebugLog(nameof(ReadMessage), command.ToString(), message.ToString());

            Interlocked.Add(ref m_ReadBytes, length);
            m_LastMessageRead = now;
            m_MessageContext.Post(x => OnMessageRecieved?.Invoke(command, message), null);
        }
示例#3
0
        /// <summary>
        /// Registers the device with the service so it's aware
        /// of events and they're handled properly.
        /// </summary>
        /// <param name="device"></param>
        private void RegisterDevice(IAudioDevice device)
        {
            AppLogging.DebugLog(nameof(RegisterDevice), device.DeviceId, device.DisplayName, device.Device.DataFlow.ToString());
            if (_devices.ContainsKey(device.Id))
            {
                device.Dispose();
                return;
            }

            _devices.Add(device.Id, device);
            device.DeviceDefaultChanged += OnDefaultDeviceChanged;
            device.DeviceVolumeChanged  += OnDeviceVolumeChanged;
            device.DeviceRemoved        += OnDeviceRemoved;

            RaiseDeviceCreated(device.Id, device.DisplayName, device.Volume, device.IsMuted, device.Flow);

            if (device.Flow == DeviceFlow.Output)
            {
                var sessionManager = AudioSessionManager2.FromMMDevice(device.Device);
                sessionManager.SessionCreated += OnSessionCreated;
                _sessionManagers.Add(device.Id, sessionManager);

                foreach (var session in sessionManager.GetSessionEnumerator())
                {
                    OnSessionCreated(session);
                }
            }
        }
示例#4
0
        private void Connect(DateTime now)
        {
            string[] portNames = null;
            try { portNames = SerialPort.GetPortNames(); }
            catch { }

            if (portNames == null || portNames.Length == 0)
            {
                return;
            }

            foreach (string portName in portNames)
            {
                string firmware = "";
                try
                {
                    AppLogging.DebugLog(nameof(Connect), portName);
                    m_SerialPort              = new SerialPort(portName, 115200);
                    m_SerialPort.ReadTimeout  = k_ReadTimeout;
                    m_SerialPort.WriteTimeout = k_WriteTimeout;
                    m_SerialPort.Open();
                    m_SerialPort.DiscardInBuffer();
                    m_SerialPort.DiscardOutBuffer();

                    WriteMessage(now, Command.TEST);
                    Thread.Sleep(20);
                    Command command = (Command)m_SerialPort.ReadByte();
                    if (command != Command.TEST)
                    {
                        throw new InvalidOperationException($"Firmware Test reply failed. Reply: '{command}' Bytes: '{m_SerialPort.BytesToRead}'");
                    }
                    firmware = m_SerialPort.ReadLine().Replace("\r", "");
                    if (!FirmwareVersions.IsCompatible(firmware))
                    {
                        throw new ArgumentException($"Incompatible Firmware: '{firmware}'.");
                    }
                    m_SerialPort.DataReceived += Read;
                    m_DeviceConnected          = true;
                    m_DeviceReady              = true;
                    m_MessageContext.Post(x => OnDeviceConnected?.Invoke(), null);
                    m_LastMessageRead = now;
                    return;
                }
                catch (Exception e)
                {
                    AppLogging.DebugLogException(nameof(Connect), e);
                    m_SerialPort.Close();
                    m_SerialPort.Dispose();
                    m_SerialPort = null;

                    if (e is ArgumentException) // Incompatible Firmware
                    {
                        m_MessageContext.Post(x => OnFirmwareIncompatible?.Invoke(firmware), null);
                    }
                }
            }
        }
示例#5
0
        private void OnDefaultDeviceChanged(object sender, DefaultDeviceChangedEventArgs e)
        {
            if (e.DataFlow != Flow.ToDataFlow())
            {
                return;
            }

            bool newDefault = e.DeviceId == DeviceId;

            if (IsDefault != newDefault)
            {
                AppLogging.DebugLog(nameof(OnDefaultDeviceChanged), DeviceId, newDefault.ToString());
                IsDefault = newDefault;
                DeviceDefaultChanged?.Invoke(this);
            }
        }
        private void WriteMessage(DateTime now, Command command, IMessage message = null)
        {
            m_WriteBuffer.SetLength(0);
            m_WriteBuffer.WriteByte((byte)command);
            message?.GetBytes(m_WriteBuffer);
            Interlocked.Add(ref m_WriteBytes, m_WriteBuffer.Length);

            // GetBuffer returns a reference to the underlying array, we can still use that after we reset the position if we store the length
            byte[] buffer = m_WriteBuffer.GetBuffer();
            int    length = (int)m_WriteBuffer.Length;

            AppLogging.DebugLog(nameof(WriteMessage), command.ToString(), message != null ? message.ToString() : "");

            try { m_SerialPort.Write(buffer, 0, length); }
            catch (Exception e)
            {
                AppLogging.DebugLogException(nameof(WriteMessage), e);
                return;
            }
            m_LastMessageWrite = now;
        }
示例#7
0
        /// <summary>
        /// Unregisters the session from the service so events
        /// are not responded to anymore.
        /// <param name="device">The device to unregister</param>
        private void UnregisterDevice(IAudioDevice device)
        {
            AppLogging.DebugLog(nameof(UnregisterDevice), device.DeviceId, device.DisplayName);
            if (_sessionManagers.ContainsKey(device.Id))
            {
                _sessionManagers[device.Id].SessionCreated -= OnSessionCreated;
                _sessionManagers.Remove(device.Id);
            }

            device.DeviceDefaultChanged -= OnDefaultDeviceChanged;
            device.DeviceVolumeChanged  -= OnDeviceVolumeChanged;
            device.DeviceRemoved        -= OnDeviceRemoved;

            if (_devices.ContainsKey(device.Id))
            {
                _devices.Remove(device.Id);
                RaiseDeviceRemoved(device.Id, device.Flow);
            }

            device.Dispose();
        }
        private void Read(DateTime now)
        {
#if POLLING_SERIAL
            try
            {
                if (m_SerialPort == null || !m_SerialPort.IsOpen || m_SerialPort.BytesToRead <= 0)
                {
                    return;
                }
            }
            catch { return; }
#endif

            Command command;
            try { command = (Command)m_SerialPort.ReadByte(); }
            catch (Exception ex)
            {
                AppLogging.DebugLogException(nameof(Read), ex);
                Interlocked.Increment(ref m_ErrorCount);
                return;
            }

            Interlocked.Increment(ref m_ReadCount);
            Interlocked.Increment(ref m_ReadBytes);
            switch (command)
            {
            case Command.TEST:
            {
                try
                {
                    var firmware = m_SerialPort.ReadLine().Replace("\r", "");
                    AppLogging.DebugLog(nameof(Read), command.ToString(), firmware);
                    m_LastMessageRead  = now;
                    m_LastMessageWrite = now;
                }
                catch (Exception e)
                {
                    AppLogging.DebugLogException(nameof(ReadMessage), e);
                    Interlocked.Increment(ref m_ErrorCount);
                    return;
                }
            }
            break;

            case Command.OK:
            {
                AppLogging.DebugLog(nameof(Read), command.ToString());
                m_DeviceReady      = true;
                m_LastMessageRead  = now;
                m_LastMessageWrite = now;
                Write(m_LastMessageRead);
            }
            break;

            case Command.SETTINGS:
                ReadMessage <DeviceSettings>(now, command);
                break;

            case Command.SESSION_INFO:
                ReadMessage <SessionInfo>(now, command);
                break;

            case Command.CURRENT_SESSION:
            case Command.ALTERNATE_SESSION:
            case Command.PREVIOUS_SESSION:
            case Command.NEXT_SESSION:
                ReadMessage <SessionData>(now, command);
                break;

            case Command.VOLUME_CURR_CHANGE:
            case Command.VOLUME_ALT_CHANGE:
            case Command.VOLUME_PREV_CHANGE:
            case Command.VOLUME_NEXT_CHANGE:
                ReadMessage <VolumeData>(now, command);
                break;

            case Command.MODE_STATES:
                ReadMessage <ModeStates>(now, command);
                break;

            case Command.ERROR:
            case Command.NONE:
            case Command.DEBUG:
                Interlocked.Increment(ref m_ErrorCount);
                break;
            }
        }
示例#9
0
        private void Read(object sender, SerialDataReceivedEventArgs e)
        {
            if (e.EventType == SerialData.Eof)
            {
                return;
            }

            Command command = (Command)m_SerialPort.ReadByte();

            Interlocked.Increment(ref m_ReadCount);
            Interlocked.Increment(ref m_ReadBytes);
            switch (command)
            {
            case Command.TEST:
            {
                var firmware = m_SerialPort.ReadLine().Replace("\r", "");
                AppLogging.DebugLog(nameof(Read), command.ToString(), firmware);
                m_LastMessageRead = DateTime.Now;
            }
            break;

            case Command.OK:
            {
                AppLogging.DebugLog(nameof(Read), command.ToString());
                m_DeviceReady = true;
                DateTime now = DateTime.Now;
                m_LastMessageRead  = now;
                m_LastMessageWrite = now;
                Write(m_LastMessageRead);
            }
            break;

            case Command.SETTINGS:
                ReadMessage <DeviceSettings>(command);
                break;

            case Command.SESSION_INFO:
                ReadMessage <SessionInfo>(command);
                break;

            case Command.CURRENT_SESSION:
            case Command.ALTERNATE_SESSION:
            case Command.PREVIOUS_SESSION:
            case Command.NEXT_SESSION:
                ReadMessage <SessionData>(command);
                break;

            case Command.VOLUME_CURR_CHANGE:
            case Command.VOLUME_ALT_CHANGE:
            case Command.VOLUME_PREV_CHANGE:
            case Command.VOLUME_NEXT_CHANGE:
                ReadMessage <VolumeData>(command);
                break;

            case Command.ERROR:
            case Command.NONE:
            case Command.DEBUG:
                Interlocked.Increment(ref m_ErrorCount);
                break;
            }
        }