private async void playButton_Click(object sender, RoutedEventArgs e) { playButton.IsEnabled = false; stationComboBox.IsEnabled = false; stopButton.IsEnabled = true; var selectedStation = stationComboBox.SelectedItem as StationItem; if (selectedStation != null) { try { shoutcastStream = await ShoutcastStreamFactory.ConnectAsync(selectedStation.Url); shoutcastStream.MetadataChanged += StreamManager_MetadataChanged; MediaPlayer.SetMediaStreamSource(shoutcastStream.MediaStreamSource); MediaPlayer.Play(); SampleRateBox.Text = "Sample Rate: " + shoutcastStream.AudioInfo.SampleRate; BitRateBox.Text = "Bit Rate: " + shoutcastStream.AudioInfo.BitRate; AudioFormatBox.Text = "Audio Format: " + Enum.GetName(typeof(UWPShoutcastMSS.Streaming.StreamAudioFormat), shoutcastStream.AudioInfo.AudioFormat); } catch (Exception ex) { playButton.IsEnabled = true; stationComboBox.IsEnabled = true; stopButton.IsEnabled = false; MessageDialog dialog = new MessageDialog("Unable to connect!"); await dialog.ShowAsync(); } } }
public ShoutcastStreamProcessor(ShoutcastStream shoutcastStream, StreamSocket socket, DataReader socketReader, DataWriter socketWriter) { this.shoutcastStream = shoutcastStream; this.socket = socket; this.socketReader = socketReader; this.socketWriter = socketWriter; }
public static async Task <ShoutcastStream> ConnectAsync(Uri serverUrl, ShoutcastStreamFactoryConnectionSettings settings) { //http://www.smackfu.com/stuff/programming/shoutcast.html ShoutcastStream shoutStream = null; ShoutcastStreamFactoryInternalConnectResult result = await ConnectInternalAsync(serverUrl, settings); SocketWrapper socketWrapper = SocketWrapperFactory.CreateSocketWrapper(result); shoutStream = new ShoutcastStream(serverUrl, settings, socketWrapper); string httpLine = result.httpResponse.Substring(0, result.httpResponse.IndexOf('\n')).Trim(); if (string.IsNullOrWhiteSpace(httpLine)) { throw new InvalidOperationException("httpLine is null or whitespace"); } var action = ParseHttpCodeAndResponse(httpLine, result.httpResponse, shoutStream); //todo handle when we get a text/html page. if (action != null) { switch (action.ActionType) { case ConnectionActionType.Success: var headers = ParseResponse(result.httpResponse, shoutStream); await shoutStream.HandleHeadersAsync(headers); return(shoutStream); case ConnectionActionType.Fail: throw action.ActionException; case ConnectionActionType.Redirect: { //clean up. shoutStream.Dispose(); return(await ConnectAsync(action.ActionUrl, settings)); } default: socketWrapper.Dispose(); throw new Exception("We weren't able to connect for some reason."); } } else { socketWrapper.Dispose(); throw new Exception("We weren't able to connect for some reason."); } }
private void stopButton_Click(object sender, RoutedEventArgs e) { playButton.IsEnabled = true; stationComboBox.IsEnabled = true; stopButton.IsEnabled = false; if (shoutcastStream != null) { shoutcastStream.MetadataChanged -= StreamManager_MetadataChanged; MediaPlayer.Stop(); MediaPlayer.Source = null; shoutcastStream.Disconnect(); shoutcastStream = null; } }
private static KeyValuePair <string, string>[] ParseResponse(string response, ShoutcastStream shoutStream) { string[] responseSplitByLine = response.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); KeyValuePair <string, string>[] headers = ParseHttpResponseToKeyPairArray(responseSplitByLine); if (shoutStream.serverSettings.RequestSongMetdata) { shoutStream.metadataInt = uint.Parse(headers.First(x => x.Key == "ICY-METAINT").Value); } shoutStream.StationInfo.StationName = headers.First(x => x.Key == "ICY-NAME").Value; if (headers.Any(x => x.Key.ToUpper() == "ICY-GENRE")) { shoutStream.StationInfo.StationGenre = headers.First(x => x.Key == "ICY-GENRE").Value; } if (headers.Any(x => x.Key.ToUpper() == "ICY-DESCRIPTION")) { shoutStream.StationInfo.StationDescription = headers.First(x => x.Key.ToUpper() == "ICY-DESCRIPTION").Value; } if (headers.Any(x => x.Key.ToUpper() == "ICY-BR")) { shoutStream.AudioInfo.BitRate = uint.Parse(headers.FirstOrDefault(x => x.Key == "ICY-BR").Value); } switch (headers.First(x => x.Key == "CONTENT-TYPE").Value.ToLower().Trim()) { case "audio/mpeg": shoutStream.AudioInfo.AudioFormat = StreamAudioFormat.MP3; break; case "audio/aac": shoutStream.AudioInfo.AudioFormat = StreamAudioFormat.AAC; break; case "audio/aacp": shoutStream.AudioInfo.AudioFormat = StreamAudioFormat.AAC_ADTS; break; } return(headers); }
private static ConnectionAction ParseHttpCodeAndResponse(string httpLine, string response, ShoutcastStream shoutStream) { var bits = httpLine.Split(new char[] { ' ' }, 3); var protocolBit = bits[0].ToUpper(); //always 'HTTP' or 'ICY int statusCode = int.Parse(bits[1]); string[] responseSplitByLine = response.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); KeyValuePair <string, string>[] headers = ParseHttpResponseToKeyPairArray(responseSplitByLine); switch (protocolBit) { case "ICY": { switch (statusCode) { case 200: return(ConnectionAction.FromSuccess()); } } break; default: if (protocolBit.StartsWith("HTTP/")) { switch (statusCode) { case 200: return(ConnectionAction.FromSuccess()); case 400: //bad request case 404: return(ConnectionAction.FromFailure()); case 302: //Found. Has the new location in the LOCATION header. { var newLocation = headers.FirstOrDefault(x => x.Key.ToUpper().Equals("LOCATION")); if (!string.IsNullOrWhiteSpace(newLocation.Value)) { //We need to connect to this url instead. Throw it back to the top. return(new ConnectionAction() { ActionType = ConnectionActionType.Redirect, ActionUrl = new Uri(newLocation.Value) }); } else { return(ConnectionAction.FromFailure()); } } } } break; } return(null); }
public ShoutcastStreamProcessor(ShoutcastStream shoutcastStream, SocketWrapper socket) { this.shoutcastStream = shoutcastStream; this.socket = socket; }