Exemple #1
0
        private void onStatusReceived(IAsyncResult res)
        {
            if (!res.IsCompleted)
            {
                return;
            }

            if (udpStatus == null)
            {
                return;
            }

            IPEndPoint rmtEndpoint = new IPEndPoint(IPAddress.Any, 9001);

            byte[] data = udpStatus.EndReceive(res, ref rmtEndpoint);

            ampIPAddress = rmtEndpoint.Address;

            lastSeenTime = DateTime.Now;

            byte[] seqData = new byte[4];
            // Convert big endian to little endian
            seqData[0] = data[3];
            seqData[1] = data[2];
            seqData[2] = data[1];
            seqData[3] = data[0];

            recvSequenceLast = recvSequence;
            recvSequence     = BitConverter.ToUInt32(seqData, 0);

            byte[] windowData = new byte[4];
            // Convert big endian to little endian
            windowData[0] = data[7];
            windowData[1] = data[6];
            windowData[2] = data[5];
            windowData[3] = data[4];

            recvWindowSize = BitConverter.ToUInt32(windowData, 0);

            byte[] statusData = new byte[4];
            // Convert big endian to little endian
            statusData[0] = data[11];
            statusData[1] = data[10];
            statusData[2] = data[9];
            statusData[3] = data[8];

            statusBitmask = BitConverter.ToUInt32(statusData, 0);

            if (!didConnectSender)
            {
                IPEndPoint epSend = new IPEndPoint(ampIPAddress, 9000);

                udpSend.Connect(epSend);

                didConnectSender = true;

                try
                {
                    if (AmplifierConnected != null)
                    {
                        AmplifierConnected(this);
                    }
                }
                catch (Exception ex) { }
            }

            // This fails if a status update comes in too quickly...
            // the first set of packets will be dequeued before the real
            // ACK comes in.  A work-around is in the send method above
            // where it waits for a litle bit after sending a reset command.

            lock (packetInProgress)
            {
                while (packetInProgress.Count > 0)
                {
                    ulong recvSeqLong = recvSequence;

                    PacketData pkt = packetInProgress.Peek();

                    // Handles the case where the amp's sequence has wrapped around
                    if (pkt.seq > 0xFFF00000 && recvSeqLong < 0x00080000)
                    {
                        recvSeqLong += 0x100000000;
                    }

                    if (pkt.seq < recvSeqLong && (recvSeqLong - pkt.seq) >= 3 * ((ulong)pkt.data.Length - 8))
                    {
                        packetInProgress.Dequeue();
                    }
                    else
                    {
                        break;
                    }
                }
            }

            try
            {
                udpStatus.BeginReceive(new AsyncCallback(onStatusReceived), null);
            }
            catch (Exception ex) { }

            try
            {
                if (StatusReceived != null)
                {
                    StatusReceived(this, recvSequence, recvWindowSize);
                }
            }
            catch (Exception ex) { }
        }
Exemple #2
0
        public int sendAudioData(byte[] data, int dataLen, bool newAudioStream)
        {
            if (dataLen > data.Length)
            {
                throw new Exception("dataLen is greater than data.Length");
            }

            if (dataLen % 6 != 0)
            {
                throw new Exception("Data must contain 2 channels of 24 bit samples, a multiple of 6 bytes per packet.");
            }

            if (dataLen > 21000)
            {
                throw new Exception("Amplifier can only accept up to 21,000 bytes per packet.");
            }

            if (!didConnectSender)
            {
                // Wait a little bit to see if it will come back...
                Thread.Sleep(2000);

                if (!didConnectSender)
                {
                    throw new Exception("Have not received any status updates yet.");
                }
            }

            if ((statusBitmask & STATUS_CLOCK_WARNING) == STATUS_CLOCK_WARNING)
            {
                throw new Exception("The audio clock does not appear to be running.");
            }

            int START_RETRIES = 7;
            int retries       = START_RETRIES;

            int packetInProgressCount;

            lock (packetInProgress)
            {
                packetInProgressCount = packetInProgress.Count;
            }

            while (retries > 0 && packetInProgressCount > 20)
            {
                Debug.WriteLine(String.Format("{0:HH:mm:ss:fff}: Retry {4}.  Expected: {1:#,##0} but have {2:#,##0}, diff={3:#,##0}",
                                              DateTime.Now, sendSequence, recvSequence, (sendSequence - recvSequence), (START_RETRIES - retries + 1)));

                resendMissingPackets();

                retries--;

                // Wait for next status to come in
                //Thread.Sleep(500);

                lock (packetInProgress)
                {
                    packetInProgressCount = packetInProgress.Count;
                }
            }

            if (retries == 0)
            {
                throw new Exception("Retried packets too many times.  Queue lenth = " + packetInProgressCount);
            }



            // Command will below will unpause automatically
            isPaused = false;

            byte[] pktBytes = new byte[dataLen + 8];

            // Command
            pktBytes[0] = 0;
            pktBytes[1] = 0;
            pktBytes[2] = 0;
            pktBytes[3] = 0;

            // Always reset mute when starting a new stream
            if (newAudioStream)
            {
                isMute = false;
            }

            if (isMute)
            {
                pktBytes[3] |= 0x01;
            }

            if (newAudioStream)
            {
                sendSequence = 0;

                // Reset sequence to 0 and stop anything that is playing
                sendCommand(CMD_RESET_I2S | CMD_SET_SEQUENCE | CMD_MUTE, sendSequence);

                // Forget any pending audio data
                lock (packetInProgress)
                {
                    packetInProgress.Clear();
                }

                // Let any status messages be processed first
                Thread.Sleep(1000);
            }

            byte[] seqData = BitConverter.GetBytes(sendSequence);

            // Sequence
            pktBytes[4] = seqData[3];
            pktBytes[5] = seqData[2];
            pktBytes[6] = seqData[1];
            pktBytes[7] = seqData[0];

            Array.Copy(data, 0, pktBytes, 8, dataLen);

            PacketData pkt = new PacketData();

            pkt.seq  = sendSequence;
            pkt.data = pktBytes;

            lock (packetInProgress)
            {
                packetInProgress.Enqueue(pkt);
            }

            int retVal = udpSend.Send(pktBytes, pktBytes.Length);

            if (retVal == pktBytes.Length)
            {
                sendSequence += (uint)dataLen;
            }

            return(retVal);
        }