예제 #1
0
        /// <summary>
        /// Determines whether the specified Object is equal to the current Object
        /// </summary>
        /// <param name="obj">The object to compare with the current object.</param>
        /// <returns>true if the specified Object is equal to the current Object; otherwise, false.</returns>
        public override bool Equals(object obj)
        {
            // We need value-type semantics.
            ShoutcastMetadata other = obj as ShoutcastMetadata;

            if (other == null)
            {
                return(false);
            }

            return(this.Title.Equals(other.Title) && this.Url.Equals(other.Url));
        }
예제 #2
0
        /// <summary>
        /// Reads or Peeks data from the circular buffer.
        /// </summary>
        /// <param name="buffer">Buffer in which to put the read or peeked data.</param>
        /// <param name="count">Number of bytes to read or peek.</param>
        /// <param name="shouldPeek">true if the data should be peeked from the circular buffer, otherwise the data is read from the circular buffer.</param>
        private void ReadOrPeekBuffer(byte[] buffer, int count, bool shouldPeek)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (this.ReadIncludesMetadata(count))
            {
                // Read to metadata chunk
                int metadataOffset = this.icyMetadata - this.metadataCount;
                byte[] metadataSizeBuffer = new byte[metadataOffset + 1];
                int bytesRead = 0;
                int metadataSize = 0;
                lock (this.syncRoot)
                {
                    bytesRead = this.circularBuffer.Peek(metadataSizeBuffer, 0, metadataOffset + 1);
                }

                if (bytesRead != (metadataOffset + 1))
                {
                    // We didn't read enough.
                    throw new IndexOutOfRangeException("metadataSize buffer not filled.");
                }

                metadataSize = metadataSizeBuffer[metadataOffset];
                int metadataByteCount = metadataSize * 16;
                int numberOfBytesAfterMetadata = count - metadataOffset;

                // We need the size of the pre-metadata bytes + metadata size byte + metadata byte count + remaining data bytes.
                byte[] metadataBuffer = new byte[metadataOffset + 1 + metadataByteCount + numberOfBytesAfterMetadata];

                lock (this.syncRoot)
                {
                    // Here is where we either Get() or Peek().  The work before is just to get the right size.
                    if (shouldPeek)
                    {
                        bytesRead = this.circularBuffer.Peek(metadataBuffer, 0, metadataBuffer.Length);
                    }
                    else
                    {
                        bytesRead = this.circularBuffer.Get(metadataBuffer, 0, metadataBuffer.Length);
                        this.metadataCount = numberOfBytesAfterMetadata;
                    }
                }

                // We are going to throw the metadata away here, as it will be read again.
                // Copy from beginning to metadata offset
                Array.Copy(metadataBuffer, 0, buffer, 0, metadataOffset);

                // Copy after metadata
                Array.Copy(metadataBuffer, metadataOffset + 1 + metadataByteCount, buffer, metadataOffset, numberOfBytesAfterMetadata);

                // Only change the metadata when we ACTUALLY read.
                if ((!shouldPeek) && (metadataSize != 0))
                {
                    string newMetadata = this.metadataEncoding.GetString(metadataBuffer, metadataOffset + 1, metadataByteCount) ?? string.Empty;

                    // TODO - Should we fire this every time the metadata changes, or whenever it is parsed.
                    // See if we need to fire the metadata changed event
                    if (string.Compare(this.currentMetadata, newMetadata) != 0)
                    {
                        this.currentMetadata = newMetadata;

                        // We need to set the current metadata on the MSS so it is always available.
                        ShoutcastMetadata metadata = new ShoutcastMetadata(this.currentMetadata);
                        Interlocked.Exchange<ShoutcastMetadata>(ref this.mediaStreamSource.currentMetadata, metadata);

                        // Since MediaElement can only be created on the UI thread, we will marshal this event over to the UI thread, plus this keeps us from blocking.
                        Deployment.Current.Dispatcher.BeginInvoke(() => this.mediaStreamSource.OnMetadataChanged());
                    }
                }
            }
            else
            {
                int bytesRead;
                lock (this.syncRoot)
                {
                    // Here is where we either Get() or Peek().  The work before is just to get the right size.
                    if (shouldPeek)
                    {
                        bytesRead = this.circularBuffer.Peek(buffer, 0, count);
                    }
                    else
                    {
                        bytesRead = this.circularBuffer.Get(buffer, 0, count);
                        this.metadataCount += bytesRead;
                    }
                }
            }
        }