private Uri m_uri; // Stream URI #endregion Fields #region Constructors //--------------------------------------------------------------------- // Constructors / Finalizer //--------------------------------------------------------------------- /// <summary> /// Instance Constructor /// </summary> /// <param name="url">URL to connect to</param> public AudioStream(string url) { // Initialize network stream members m_uri = new Uri(url); m_tcpClient = new TcpClient(); m_headers = new Dictionary<string, string>(); m_metadataInterval = -1; // Initialize buffer members m_buffer = null; m_stop = new ManualResetEvent(false); }
//--------------------------------------------------------------------- // Member Functions //--------------------------------------------------------------------- /// <summary> /// Connects to the stream, processes headers, and begins buffering /// </summary> /// <param name="embedMetadata">Flag to include metadata if possible, check on return</param> public void Connect(ref bool embedMetadata) { string header; // A single HTTP header string if (m_disposed) throw new ObjectDisposedException(typeof(AudioStream).Name); if (m_connected) throw new InvalidOperationException("Audio stream has already been connected"); // Attempt to to connect to the provided host and port m_tcpClient.Connect(m_uri.Host, m_uri.Port); // Set up the request HTTP headers to pass to the server string requestHeaders = (embedMetadata) ? String.Format("GET {0} HTTP/1.0\r\nIcy-Metadata:1\r\n\r\n", m_uri.AbsolutePath) : String.Format("GET {0} HTTP/1.0\r\n\r\n", m_uri.AbsolutePath); byte[] requestHeaderBits = Encoding.UTF8.GetBytes(requestHeaders); m_tcpClient.GetStream().Write(requestHeaderBits, 0, requestHeaderBits.Length); // Read the HTTP response headers from the connection StreamReader sr = new StreamReader(m_tcpClient.GetStream()); // The first header must end with "200 OK". This allows for both HTTP and ICY responses. header = sr.ReadLine(); if (!header.EndsWith("200 OK")) throw new Exception("Invalid response [" + header + "] received from server"); // Read and process the remaining response headers, stopping when the blank one is found. // This should position the TCP stream at the head of the actual data stream header = sr.ReadLine(); while (!String.IsNullOrEmpty(header)) { // Split the header into KEY:VALUE components int colon = header.IndexOf(':'); if ((colon > 0) && (header.Length > colon + 1)) { string key = header.Substring(0, colon); string value = header.Substring(colon + 1); // SPECIAL HEADER: ICY-METAINT if (String.Compare(key, "Icy-Metaint", true) == 0) m_metadataInterval = Int32.Parse(value.Trim()); // SPECIAL HEADER: CONTENT-TYPE else if (String.Compare(key, "content-type", true) == 0) m_contentType = value.Trim(); // EVERYTHING ELSE else if(!m_headers.ContainsKey(key)) m_headers.Add(key, value); } header = sr.ReadLine(); // Next header } // Set the return value for embedded metadata and create the audio stream buffer embedMetadata = (m_metadataInterval > 0); m_buffer = new AudioStreamBuffer(BUFFER_SIZE, embedMetadata); // Launch the background worker thread to begin buffering the audio data m_bufferThread = new Thread(new ThreadStart(BufferThreadProc)); m_bufferThread.IsBackground = true; m_bufferThread.Priority = ThreadPriority.AboveNormal; m_bufferThread.Start(); m_connected = true; // Stream is now connected }