static void Main(string[] args) { if (args.Count() > 1) { switch (args[0]) { case "-url": using (Radio radio = new Radio(args[1])) { radio.OnCurrentSongChanged += (sender, eventArgs) => { Console.WriteLine(eventArgs.NewSong.Artist + " - " + eventArgs.NewSong.Title); }; radio.Start(); Console.ReadLine(); GC.KeepAlive(radio); } break; } } }
public void Start(string pluginsPath = null) { if (string.IsNullOrEmpty(Url)) { Radio.Log("The specified Url is empty.", this); return; } if (pluginsPath == null) { pluginsPath = Directory.GetCurrentDirectory() + "\\plugins"; } var plugins = pluginManager.LoadPlugins(pluginsPath); OnPluginsLoaded?.Invoke(this, new PluginEventArgs(plugins)); OnCurrentSongChanged += pluginManager.OnCurrentSongChanged; OnStreamStart += pluginManager.OnStreamStart; OnStreamUpdate += pluginManager.OnStreamUpdate; OnStreamOver += pluginManager.OnStreamOver; Running = true; runningTask = Task.Run(GetHttpStreamAsync); }
void GetHttpStream() { do { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url); request.Headers.Add("icy-metadata", "1"); request.ReadWriteTimeout = 10 * 1000; request.Timeout = 10 * 1000; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { //get the position of metadata int metaInt = Convert.ToInt32(response.GetResponseHeader("icy-metaint")); using (Stream socketStream = response.GetResponseStream()) { byte[] buffer = new byte[16384]; int metadataLength = 0; int streamPosition = 0; int bufferPosition = 0; int readBytes = 0; StringBuilder metadataSb = new StringBuilder(); while (Running) { if (bufferPosition >= readBytes) { readBytes = socketStream.Read(buffer, 0, buffer.Length); bufferPosition = 0; } if (readBytes <= 0) { Radio.Log("Stream over", this); break; } if (metadataLength == 0) { if (streamPosition + readBytes - bufferPosition <= metaInt) { streamPosition += readBytes - bufferPosition; ProcessStreamData(buffer, ref bufferPosition, readBytes - bufferPosition); continue; } ProcessStreamData(buffer, ref bufferPosition, metaInt - streamPosition); metadataLength = Convert.ToInt32(buffer[bufferPosition++]) * 16; //check if there's any metadata, otherwise skip to next block if (metadataLength == 0) { streamPosition = Math.Min(readBytes - bufferPosition, metaInt); ProcessStreamData(buffer, ref bufferPosition, streamPosition); continue; } } //get the metadata and reset the position while (bufferPosition < readBytes) { metadataSb.Append(Convert.ToChar(buffer[bufferPosition++])); metadataLength--; if (metadataLength == 0) { Metadata = metadataSb.ToString(); metadataSb.Clear(); streamPosition = Math.Min(readBytes - bufferPosition, metaInt); ProcessStreamData(buffer, ref bufferPosition, streamPosition); break; } } } } } } catch (IOException ex) { Radio.Log(string.Format("Handled IOException, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } catch (SocketException ex) { Radio.Log(string.Format("Handled SocketException, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } catch (WebException ex) { Radio.Log(string.Format("Handled WebException, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } } while (Running); }
async Task GetHttpStreamAsync() { do { try { using var streamHandler = await BaseStreamHandler.GetStreamHandler(Url, httpClient); await streamHandler.StartAsync(); { //get the position of metadata int metaInt = streamHandler.GetIceCastMetaInterval(); using MemoryStream metadataData = new MemoryStream(); byte[] buffer = null; int metadataLength = 0; int streamPosition = 0; int bufferPosition = 0; int readBytes = 0; OnStreamStart?.Invoke(this, new StreamStartEventArgs(streamHandler.GetCodec())); while (Running) { if (bufferPosition >= readBytes) { (readBytes, buffer) = await streamHandler.ReadAsync(); bufferPosition = 0; } if (readBytes <= 0) { Radio.Log("Stream over", this); break; } if (metadataLength == 0) { if (metaInt == 0 || streamPosition + readBytes - bufferPosition <= metaInt) { streamPosition += readBytes - bufferPosition; ProcessStreamData(buffer, ref bufferPosition, readBytes - bufferPosition); continue; } ProcessStreamData(buffer, ref bufferPosition, metaInt - streamPosition); metadataLength = Convert.ToInt32(buffer[bufferPosition++]) * 16; //check if there's any metadata, otherwise skip to next block if (metadataLength == 0) { streamPosition = Math.Min(readBytes - bufferPosition, metaInt); ProcessStreamData(buffer, ref bufferPosition, streamPosition); continue; } } //get the metadata and reset the position while (bufferPosition < readBytes) { metadataData.WriteByte(buffer[bufferPosition++]); metadataLength--; if (metadataLength == 0) { var metadataBuffer = metadataData.ToArray(); Metadata = Encoding.UTF8.GetString(metadataBuffer); metadataData.SetLength(0); streamPosition = Math.Min(readBytes - bufferPosition, metaInt); ProcessStreamData(buffer, ref bufferPosition, streamPosition); break; } } } } } catch (IOException ex) { Radio.Log(string.Format("Handled IOException, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } catch (SocketException ex) { Radio.Log(string.Format("Handled SocketException, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } catch (WebException ex) { Radio.Log(string.Format("Handled WebException, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } catch (Exception ex) { Radio.Log(string.Format("Handled Exception, reconnecting. Details:\n{0}\n{1}", ex.Message, ex.StackTrace), this); OnStreamOver?.Invoke(this, new StreamOverEventArgs()); } } while (Running); }