/// <summary> /// Cleans up all associated streaming resources. /// </summary> private void CleanupAudioStream() { var tempStream = this.audioStream; this.audioStream = null; if (tempStream != null) { tempStream.Closed += (s, e) => { this.OnClosed(); }; tempStream.Dispose(); } }
/// <summary> /// Parses the passed in MediaStream to find the first frame and signals /// to its parent MediaElement that it is ready to begin playback by calling /// ReportOpenMediaCompleted. /// </summary> protected override void OpenMediaAsync() { System.Diagnostics.Debug.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ": OpenMediaAsync()"); // So, here is why this is a little weird. // The Shoutcast server software has the ability to provide web pages. These pages just happen to be served from the SAME address as the media stream. // Putting a "/;" at the end of the Uri will tell the Shoutcast server that we aren't a web browser, so stream the data. The problem is that not ALL // Shoutcast servers are configured that way. So, we have to do a request to get the content type. If it is text/html, we append the "/;" and move on. // If it is an empty string, 99.9% of the time, this will be the media stream (If it's an ICY stream, the ICY "headers" don't parse properly). The ShoutcastStream // will handle this case, so we let it go through. HttpWebRequest contentTypeRequest = ShoutcastMediaStreamSource.CreateHttpWebRequest(this.StreamUri, this.IncludeMetadata); contentTypeRequest.BeginGetResponse( ia1 => { HttpWebRequest req1 = ia1.AsyncState as HttpWebRequest; try { HttpWebResponse res1 = (HttpWebResponse)req1.EndGetResponse(ia1); string contentType = res1.ContentType; if ((contentType == string.Empty) || (contentType == "audio/mpeg")) { try { this.audioStream = new ShoutcastStream(this, res1); this.audioStreamDescription = this.audioStream.AudioStreamDescription; this.ReportOpenMediaCompleted(this.audioStream.AudioSourceAttributes, new MediaStreamDescription[] { this.audioStream.AudioStreamDescription }); } catch (Exception ex) { this.CleanupAudioStream(); this.ErrorOccurred(ex.Message); } } else { // Close the original response. We need another one. res1.Close(); res1 = null; if (!this.StreamUri.OriginalString.EndsWith("/", StringComparison.Ordinal)) { this.StreamUri = new Uri(this.StreamUri.OriginalString + "/;", UriKind.Absolute); } else { this.StreamUri = new Uri(this.StreamUri.OriginalString + ";", UriKind.Absolute); } HttpWebRequest streamRequest = ShoutcastMediaStreamSource.CreateHttpWebRequest(this.StreamUri, this.IncludeMetadata); streamRequest.BeginGetResponse( ia => { HttpWebRequest req = ia.AsyncState as HttpWebRequest; try { HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(ia); this.audioStream = new ShoutcastStream(this, res); this.audioStreamDescription = this.audioStream.AudioStreamDescription; this.ReportOpenMediaCompleted(this.audioStream.AudioSourceAttributes, new MediaStreamDescription[] { this.audioStream.AudioStreamDescription }); } catch (Exception ex) { if (res1 != null) { res1.Close(); } this.CleanupAudioStream(); this.ErrorOccurred(ex.Message); } }, streamRequest); } } catch (Exception ex) { this.CleanupAudioStream(); this.ErrorOccurred(ex.Message); } }, contentTypeRequest); }