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."); } }
internal ShoutcastStream(Uri serverUrl, ShoutcastStreamFactoryConnectionSettings settings, SocketWrapper socketWrapper) { this.socket = socketWrapper; this.serverUrl = serverUrl; this.serverSettings = settings; StationInfo = new ServerStationInfo(); AudioInfo = new ServerAudioInfo(); cancelTokenSource = new CancellationTokenSource(); //MediaStreamSource = new MediaStreamSource(null); streamProcessor = new ShoutcastStreamProcessor(this, socket); }
internal static async Task <ShoutcastStreamFactoryInternalConnectResult> ConnectInternalAsync(Uri serverUrl, ShoutcastStreamFactoryConnectionSettings settings) { //abstracted the connection bit to allow for reconnecting from the ShoutcastStream object. ShoutcastStreamFactoryInternalConnectResult result = new ShoutcastStreamFactoryInternalConnectResult(); result.socket = new StreamSocket(); result.socket.Control.QualityOfService = SocketQualityOfService.LowLatency; await result.socket.ConnectAsync(new Windows.Networking.HostName(serverUrl.Host), serverUrl.Port.ToString()); result.socketWriter = new DataWriter(result.socket.OutputStream); result.socketReader = new DataReader(result.socket.InputStream); //build a http request string portStr = ""; switch (serverUrl.Scheme.ToLower()) { case "http": portStr = serverUrl.Port != 80 ? ":" + serverUrl.Port : ""; break; case "https": portStr = serverUrl.Port != 443 ? ":" + serverUrl.Port : ""; throw new NotImplementedException("https streams are currently not supported."); break; } StringBuilder requestBuilder = new StringBuilder(); requestBuilder.AppendLine("GET " + serverUrl.LocalPath + settings.RelativePath + " HTTP/1.1"); if (settings.RequestSongMetdata) { requestBuilder.AppendLine("Icy-MetaData: 1"); } requestBuilder.AppendLine("Host: " + serverUrl.Host + portStr); requestBuilder.AppendLine("Connection: Keep-Alive"); requestBuilder.AppendLine("User-Agent: " + settings.UserAgent); requestBuilder.AppendLine(); //send the http request result.socketWriter.WriteString(requestBuilder.ToString()); await result.socketWriter.StoreAsync(); await result.socketWriter.FlushAsync(); //start reading the headers from the response string response = string.Empty; while (!response.EndsWith(Environment.NewLine + Environment.NewLine)) //loop until we get the double line-ending signifying the end of the headers { await result.socketReader.LoadAsync(1); response += result.socketReader.ReadString(1); } result.httpResponse = response; return(result); }