using System; using System.Collections.Generic; using System.Text; using System.Net; using System.IO; using System.Web; using CUETools.Codecs; namespace CUETools.Codecs.Icecast { public class IcecastWriter: IAudioDest { private long _sampleOffset = 0; private AudioPCMConfig pcm = AudioPCMConfig.RedBook; private LAME.LAMEEncoderCBR encoder = null; private HttpWebRequest req = null; private HttpWebResponse resp = null; private Stream reqStream; private IcecastSettingsData settings = null; public IAudioDest Encoder { get { return encoder; } } public IcecastWriter(AudioPCMConfig pcm, IcecastSettingsData settings) { this.pcm = pcm; this.settings = settings; } #region IAudioDest Members public HttpWebResponse Response { get { return resp; } } public void Connect() { Uri uri = new Uri("http://" + settings.Server + ":" + settings.Port + settings.Mount); req = (HttpWebRequest)WebRequest.Create(uri); //req.Proxy = proxy; //req.UserAgent = userAgent; req.ProtocolVersion = HttpVersion.Version10; // new Version("ICE/1.0"); req.Method = "SOURCE"; req.ContentType = "audio/mpeg"; req.Headers.Add("ice-name", settings.Name ?? "no name"); req.Headers.Add("ice-public", "1"); if ((settings.Url ?? "") != "") req.Headers.Add("ice-url", settings.Url); if ((settings.Genre ?? "") != "") req.Headers.Add("ice-genre", settings.Genre); if ((settings.Desctiption ?? "") != "") req.Headers.Add("ice-description", settings.Desctiption); req.Headers.Add("Authorization", string.Format("Basic {0}", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("source:{0}", settings.Password))))); req.Timeout = System.Threading.Timeout.Infinite; req.ReadWriteTimeout = System.Threading.Timeout.Infinite; //req.ContentLength = 999999999; req.KeepAlive = false; req.SendChunked = true; req.AllowWriteStreamBuffering = false; req.CachePolicy = new System.Net.Cache.HttpRequestCachePolicy(System.Net.Cache.HttpRequestCacheLevel.BypassCache); System.Reflection.PropertyInfo pi = typeof(ServicePoint).GetProperty("HttpBehaviour", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); pi.SetValue(req.ServicePoint, pi.PropertyType.GetField("Unknown").GetValue(null), null); reqStream = req.GetRequestStream(); System.Reflection.FieldInfo fi = reqStream.GetType().GetField("m_HttpWriteMode", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); fi.SetValue(reqStream, fi.FieldType.GetField("Buffer").GetValue(null)); System.Reflection.MethodInfo mi = reqStream.GetType().GetMethod("CallDone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, new Type[0], null); mi.Invoke(reqStream, null); try { resp = req.GetResponse() as HttpWebResponse; if (resp.StatusCode == HttpStatusCode.OK) { encoder = new CUETools.Codecs.LAME.LAMEEncoderCBR("", reqStream, AudioPCMConfig.RedBook); encoder.Options = settings.MP3Options; } } catch (WebException ex) { if (ex.Status == WebExceptionStatus.ProtocolError) resp = ex.Response as HttpWebResponse; else throw ex; } } public void UpdateMetadata(string artist, string title) { string song = ((artist ?? "") != "" && (title ?? "") != "") ? artist + " - " + title : (title ?? ""); string metadata = ""; //if (station != "") // metadata += "&name=" + Uri.EscapeDataString(station); if (song != "") metadata += "&song=" + Uri.EscapeDataString(song); Uri uri = new Uri("http://" + settings.Server + ":" + settings.Port + "/admin/metadata?mode=updinfo&mount=" + settings.Mount + metadata); HttpWebRequest req2 = (HttpWebRequest)WebRequest.Create(uri); req2.Method = "GET"; req2.Credentials = new NetworkCredential("source", settings.Password); //req.Proxy = proxy; //req.UserAgent = userAgent; //req2.Headers.Add("Authorization", string.Format("Basic {0}", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("source:{0}", settings.Password))))); HttpStatusCode accResult = HttpStatusCode.OK; try { HttpWebResponse resp = (HttpWebResponse)req2.GetResponse(); accResult = resp.StatusCode; if (accResult == HttpStatusCode.OK) { } resp.Close(); } catch (WebException ex) { if (ex.Status == WebExceptionStatus.ProtocolError) accResult = ((HttpWebResponse)ex.Response).StatusCode; else accResult = HttpStatusCode.BadRequest; } } public void Close() { if (encoder != null) { encoder.Close(); encoder = null; } if (reqStream != null) { reqStream.Close(); reqStream = null; } if (resp != null) { resp.Close(); resp = null; } if (req != null) { req.Abort(); req = null; } } public void Delete() { if (encoder != null) { encoder.Delete(); encoder = null; } if (reqStream != null) { reqStream.Close(); reqStream = null; } if (resp != null) { resp.Close(); resp = null; } if (req != null) { req.Abort(); req = null; } } AudioBuffer tmp; public void Write(AudioBuffer src) { if (encoder == null) throw new Exception("not connected"); if (tmp == null || tmp.Size < src.Size) tmp = new AudioBuffer(AudioPCMConfig.RedBook, src.Size); tmp.Prepare(-1); Buffer.BlockCopy(src.Float, 0, tmp.Float, 0, src.Length * 8); tmp.Length = src.Length; encoder.Write(tmp); } public long Position { get { return _sampleOffset; } } public long BlockSize { set { } } public long FinalSampleCount { set { ; } } public int CompressionLevel { get { return 0; } set { } } public string Options { set { if (value == null || value == "") return; throw new Exception("Unsupported options " + value); } } public AudioPCMConfig PCM { get { return pcm; } } public string Path { get { return null; } } #endregion public long BytesWritten { get { return encoder == null ? 0 : encoder.BytesWritten; } } } public class IcecastSettingsData { private string server; private string port = "8000"; private string password; private string mount; private string name; private string description; private string url; private string genre; private string mp3Options = "-m j -b 192"; public string Server { get { return server; } set { server = value; } } public string Port { get { return port; } set { port = value; } } public string Password { get { return password; } set { password = value; } } public string Mount { get { return mount; } set { mount = value; } } public string Name { get { return name; } set { name = value; } } public string Desctiption { get { return description; } set { description = value; } } public string Url { get { return url; } set { url = value; } } public string Genre { get { return genre; } set { genre = value; } } public string MP3Options { get { return mp3Options; } set { mp3Options = value; } } } }