/// <summary> /// Raises the ResultsRetrieved event /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the original request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the original freetext query or the original genre name /// </param> public void RaiseRequestResultRetrieved(LiveRadioRequestType request_type, string query) { List <DatabaseTrackInfo> result; try { List <DatabaseTrackInfo> raw_result; if (request_type == LiveRadioRequestType.ByGenre) { raw_result = new List <DatabaseTrackInfo> (cached_results["Genre:" + query].ToArray()); } else { raw_result = new List <DatabaseTrackInfo> (cached_results[query].ToArray()); } result = new List <DatabaseTrackInfo> (raw_result); foreach (DatabaseTrackInfo track in raw_result) { result[result.IndexOf(track)] = new DatabaseTrackInfo(track); } } catch (Exception e) { result = null; Hyena.Log.DebugFormat("[LiveRadioBasePlugin\"{0}\"]<RaiseRequestResultRetrieved> error {1}", Name, e.Message); RaiseErrorReturned("General Error", e.Message); } OnRequestResultRetrieved(request_type, query, result); }
/// <summary> /// Lookup the query in the cached station track entries /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { string key; if (request_type == LiveRadioRequestType.ByGenre) { key = new Genre(query).GenreKey; if (!cached_results.ContainsKey(key)) { cached_results.Add(key, new List <DatabaseTrackInfo> ()); } } if (request_type == LiveRadioRequestType.ByFreetext) { key = query; if (!cached_results.ContainsKey(key)) { List <DatabaseTrackInfo> newlist = new List <DatabaseTrackInfo> (); foreach (KeyValuePair <string, List <DatabaseTrackInfo> > entry in cached_results) { newlist.AddRange(entry.Value.FindAll(delegate(DatabaseTrackInfo track) { return(QueryString(track, query)); })); } cached_results.Add(key, newlist); } } }
/// <summary> /// Method to invoke the RequestResultRetrieved event /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the original request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the original freetext query or the original genre name /// </param> /// <param name="result"> /// A <see cref="List<DatabaseTrackInfo>"/> -- the resulting list of DatabaseTrackInfo objects for the query /// </param> protected void OnRequestResultRetrieved(LiveRadioRequestType request_type, string query, List <DatabaseTrackInfo> result) { RequestResultRetrievedEventHandler handler = RequestResultRetrieved; if (handler != null) { handler(this, query, request_type, result); } }
/// <summary> /// Method capsuling the actual RetrieveRequest worker method with a background worker thread /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> public void ExecuteRequest(LiveRadioRequestType request_type, string query) { BackgroundWorker request_thread = new BackgroundWorker(); request_thread.DoWork += DoExecuteRequest; request_thread.RunWorkerCompleted += OnDoExecuteRequestFinished; LiveRadioRequestObject request_object = new LiveRadioRequestObject(request_type, query); request_thread.RunWorkerAsync(request_object); }
/// <summary> /// Event Handler for the event that a plugin has retreived a result list for a query /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> -- the plugin that has retrieved the results /// </param> /// <param name="request"> /// A <see cref="System.String"/> -- the original request string, either freetext or the genre name /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the original request type /// </param> /// <param name="result"> /// A <see cref="List<DatabaseTrackInfo>"/> -- the results list /// </param> void OnPluginRequestResultRetrieved(object sender, string request, LiveRadioRequestType request_type, List <DatabaseTrackInfo> result) { if (result != null) { ILiveRadioPlugin plugin = sender as ILiveRadioPlugin; AddStatistic(LiveRadioStatisticType.Message, plugin.Name, AddinManager.CurrentLocalizer.GetString("Requested Results Returned"), AddinManager.CurrentLocalizer.GetString("The plugin has returned a list of results for a genre or freetext query"), result.Count); } }
/// <summary> /// Retrieve and parse a live query on the shoutcast directory /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { string request; if (request_type == LiveRadioRequestType.ByGenre) { request = base_url + request_url + genre_request + query; } else { request = base_url + request_url + freetext_request + query; } XmlDocument document = RetrieveXml(request); if (document != null) { ParseXmlResponse(document, request_type, query); } }
/// <summary> /// Lookup the query in the cached station track entries /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest (LiveRadioRequestType request_type, string query) { string key; if (request_type == LiveRadioRequestType.ByGenre) { key = new Genre(query).GenreKey; if (!cached_results.ContainsKey (key)) { cached_results.Add (key, new List<DatabaseTrackInfo> ()); } } if (request_type == LiveRadioRequestType.ByFreetext) { key = query; if (!cached_results.ContainsKey (key)) { List<DatabaseTrackInfo> newlist = new List<DatabaseTrackInfo> (); foreach (KeyValuePair<string, List<DatabaseTrackInfo>> entry in cached_results) { newlist.AddRange (entry.Value.FindAll (delegate (DatabaseTrackInfo track) { return QueryString (track, query); })); } cached_results.Add (key, newlist); } } }
/// <summary> /// Retrieve and parse a live query on the realradios directory /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; } else { key = query; } if (cached_results.ContainsKey(key)) { return; } string request; if (request_type == LiveRadioRequestType.ByGenre) { request = genres.Find(delegate(Genre g) { return(g.Name.Equals(query)); } ).Hyperlink; } else { request = base_url + freetext_url + query; } string document = RetrieveHtml(request); if (document != null) { ParseHtmlResponse(document, request_type, query); } }
/// <summary> /// Retrieve and parse a live query on the shoutcast directory /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { if (request_type == LiveRadioRequestType.ByGenre) { XmlDocument document = RetrieveXml(base_url + genre_url + query + ".xspf"); if (document != null) { ParseXspf(document, new Genre(query)); } } else { if (cached_results.ContainsKey(query)) { return; } string doc = RetrieveHtml(search_url + freetext_request + query); if (!String.IsNullOrEmpty(doc)) { ParseSearchResult(doc, query); } } }
/// <summary> /// Handles when a new result for a previous query request is received from the corresponding plugin. Transfers the /// received result to the plugin's source, and if there are none, set up a fake entry. /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> -- The plugin that sent the results. Implements ILiveRadioPlugin. /// </param> /// <param name="request"> /// A <see cref="System.String"/> -- The requested query string, either a genre name or the freetext (see request_type). /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- The type of the request. /// </param> /// <param name="result"> /// A <see cref="List<DatabaseTrackInfo>"/> -- A list of DatabaseTrackInfo objects that fulfil the query. /// </param> void OnPluginRequestResultRetrieved(object sender, string request, LiveRadioRequestType request_type, List <DatabaseTrackInfo> result) { if ((request_type == LiveRadioRequestType.ByFreetext) || (filter_box.GetSelectedGenre().Name.Equals(request) && request_type == LiveRadioRequestType.ByGenre)) { if (result == null) { SetFakeTrack(AddinManager.CurrentLocalizer.GetString("Error... Please Reload")); } else if (result.Count > 0) { plugin.PluginSource.SetStations(result); main_scrolled_window.Sensitive = true; } else { string message = (request_type == LiveRadioRequestType.ByGenre ? "Error... Please Reload" : "No Results"); SetFakeTrack(AddinManager.CurrentLocalizer.GetString(message)); } } }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseXmlResponse(XmlDocument xml_response, LiveRadioRequestType request_type, string query) { string tunein_url = ""; XmlNodeList XML_tunein_nodes = xml_response.GetElementsByTagName("tunein"); foreach (XmlNode node in XML_tunein_nodes) { XmlAttributeCollection xml_attributes = node.Attributes; try { tunein_url = xml_attributes.GetNamedItem("base").InnerText; break; } catch (Exception e) { Log.Warning("[ShoutCastPlugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned("XML Parse Error", e.Message); return; } } XmlNodeList XML_station_nodes = xml_response.GetElementsByTagName("station"); string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; if (!cached_results.ContainsKey(key)) { cached_results[key] = new List <DatabaseTrackInfo> (XML_station_nodes.Count); } } else { key = query; if (!cached_results.ContainsKey(key)) { cached_results[key] = new List <DatabaseTrackInfo> (XML_station_nodes.Count); } } cached_results[key].Clear(); foreach (XmlNode node in XML_station_nodes) { XmlAttributeCollection xml_attributes = node.Attributes; try { string name = xml_attributes.GetNamedItem("name").InnerText; string media_type = xml_attributes.GetNamedItem("mt").InnerText; string id = xml_attributes.GetNamedItem("id").InnerText; string genre = xml_attributes.GetNamedItem("genre").InnerText; string now_playing = xml_attributes.GetNamedItem("ct").InnerText; string bitrate = xml_attributes.GetNamedItem("br").InnerText; int id_int; int bitrate_int; if (!Int32.TryParse(id.Trim(), out id_int)) { continue; //Something wrong with id, skip this } DatabaseTrackInfo new_station = new DatabaseTrackInfo(); new_station.Uri = new SafeUri(play_url + tunein_url + "?id=" + id); new_station.ArtistName = "www.shoutcast.com"; new_station.Genre = genre; new_station.TrackTitle = name; new_station.Comment = now_playing; new_station.AlbumTitle = now_playing; new_station.MimeType = media_type; new_station.ExternalId = id_int; new_station.PrimarySource = source; new_station.IsLive = true; Int32.TryParse(bitrate.Trim(), out bitrate_int); new_station.BitRate = bitrate_int; new_station.IsLive = true; cached_results[key].Add(new_station); } catch (Exception e) { Log.Warning("[ShoutCastPlugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned("XML Parse Error", e.Message); continue; } } }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseXmlResponse(XmlDocument xml_response, LiveRadioRequestType request_type, string query) { Log.Debug ("[Live365Plugin] <ParseXmlResponse> Start"); string session = GetSession (); List<string> pages = new List<string> (); pages.Add(null); XmlNodeList pagination_nodes = xml_response.GetElementsByTagName ("PAGINATION_PAGES"); foreach (XmlNode node in pagination_nodes) { string url = null; bool url_valid = false; XmlNodeList page_nodes = node.ChildNodes; foreach (XmlNode page_node in page_nodes) { try { if (page_node.LocalName.Equals("PAGINATION_DESC") && !page_node.InnerText.Trim ().Equals ("1") && !page_node.InnerText.Trim ().Equals ("Next")) url_valid = true; if (page_node.LocalName.Equals("PAGINATION_LINK")) url = page_node.InnerText; } catch (Exception e) { Log.Exception ("[Live365Plugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned ("XML Parse Error", e.Message); return; } } if (!String.IsNullOrEmpty(url) && url_valid) pages.Add(url); } Log.Debug ("[Live365Plugin] <ParseXmlResponse> analyzing stations"); string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; if (!cached_results.ContainsKey (key)) { cached_results[key] = new List<DatabaseTrackInfo> (); } } else { key = query; if (!cached_results.ContainsKey (key)) { cached_results[key] = new List<DatabaseTrackInfo> (); } } cached_results[key].Clear (); foreach (string page in pages) { XmlDocument doc; if (String.IsNullOrEmpty(page)) { doc = xml_response; } else { doc = RetrieveXml(page); } XmlNodeList XML_station_nodes = doc.GetElementsByTagName ("LIVE365_STATION"); foreach (XmlNode node in XML_station_nodes) { string name = null; string access = null; string ex_id = null; string url = null; string broadcaster = null; string description = null; string keywords = null; string genre = null; string bitrate = null; string rating = null; string status = null; string location = null; XmlNodeList childnodes = node.ChildNodes; foreach (XmlNode child in childnodes) { try { if (child.LocalName.Equals ("STATION_ADDRESS")) url = child.InnerText; else if (child.LocalName.Equals ("STATION_ID")) ex_id = child.InnerText; else if (child.LocalName.Equals ("STATION_BROADCASTER")) broadcaster = child.InnerText; else if (child.LocalName.Equals ("STATION_TITLE")) name = child.InnerText; else if (child.LocalName.Equals ("STATION_DESCRIPTION")) description = child.InnerText; else if (child.LocalName.Equals ("STATION_KEYWORDS")) keywords = child.InnerText; else if (child.LocalName.Equals ("STATION_GENRE")) genre = child.InnerText; else if (child.LocalName.Equals ("STATION_CONNECTION")) bitrate = child.InnerText; else if (child.LocalName.Equals ("STATION_RATING")) rating = child.InnerText; else if (child.LocalName.Equals ("STATION_STATUS")) status = child.InnerText; else if (child.LocalName.Equals ("LISTENER_ACCESS")) access = child.InnerText; else if (child.LocalName.Equals ("STATION_LOCATION")) location = child.InnerText; } catch (Exception e) { Log.Exception ("[Live365Plugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned ("General Error", e.Message); continue; } } int bitrate_int; int id_int; int rating_int; if (!String.IsNullOrEmpty (access) && !String.IsNullOrEmpty (status) && (access.Equals ("PUBLIC") || UseCredentials) && status.Equals ("OK")) { DatabaseTrackInfo new_station = new DatabaseTrackInfo (); if (UseCredentials) { url = url.Replace (replace_url, playlist_url); url += session; } new_station.Uri = new SafeUri (url); new_station.ArtistName = broadcaster; new_station.Genre = genre; new_station.TrackTitle = name; new_station.Comment = description + location + keywords; Int32.TryParse (rating.Trim (), out rating_int); new_station.Rating = rating_int; Int32.TryParse (ex_id.Trim (), out id_int); new_station.ExternalId = id_int; new_station.PrimarySource = source; new_station.IsLive = true; Int32.TryParse (bitrate.Trim (), out bitrate_int); new_station.BitRate = bitrate_int; new_station.IsLive = true; cached_results[key].Add (new_station); } } } Log.Debug ("[Live365Plugin] <ParseXmlResponse> End"); }
/// <summary> /// Event Handler for the event that a plugin has retreived a result list for a query /// </summary> /// <param name="sender"> /// A <see cref="System.Object"/> -- the plugin that has retrieved the results /// </param> /// <param name="request"> /// A <see cref="System.String"/> -- the original request string, either freetext or the genre name /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the original request type /// </param> /// <param name="result"> /// A <see cref="List<DatabaseTrackInfo>"/> -- the results list /// </param> void OnPluginRequestResultRetrieved(object sender, string request, LiveRadioRequestType request_type, List<DatabaseTrackInfo> result) { if (result != null) { ILiveRadioPlugin plugin = sender as ILiveRadioPlugin; AddStatistic (LiveRadioStatisticType.Message, plugin.Name, AddinManager.CurrentLocalizer.GetString ("Requested Results Returned"), AddinManager.CurrentLocalizer.GetString ("The plugin has returned a list of results for a genre or freetext query"), result.Count); } }
public LiveRadioRequestObject(LiveRadioRequestType request_type, string query) : base() { this.query = query; this.request_type = request_type; }
/// <summary> /// Retrieve and parse a live query on the shoutcast directory /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { string request; if (request_type == LiveRadioRequestType.ByGenre) { request = base_url + request_url + genre_request + query; } else { request = base_url + request_url + freetext_request + query; } XmlDocument document = RetrieveXml(request); if (document != null) ParseXmlResponse(document, request_type, query); }
/// <summary> /// Actual method that does the work of retrieving the results of a user query from an outside /// source. This method must take care of retrieving the data (possibly using the provided /// RetrieveXML method). parsing it, and filling the /// /// Dictionary<string key, List<DatabaseTrackInfo> track> cached_results /// /// member of this class with the result. /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected abstract void RetrieveRequest(LiveRadioRequestType request_type, string query);
/// <summary> /// Method capsuling the actual RetrieveRequest worker method with a background worker thread /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> public void ExecuteRequest(LiveRadioRequestType request_type, string query) { BackgroundWorker request_thread = new BackgroundWorker (); request_thread.DoWork += DoExecuteRequest; request_thread.RunWorkerCompleted += OnDoExecuteRequestFinished; LiveRadioRequestObject request_object = new LiveRadioRequestObject (request_type, query); request_thread.RunWorkerAsync (request_object); }
/// <summary> /// Raises the ResultsRetrieved event /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the original request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the original freetext query or the original genre name /// </param> public void RaiseRequestResultRetrieved(LiveRadioRequestType request_type, string query) { List<DatabaseTrackInfo> result; try { if (request_type == LiveRadioRequestType.ByGenre) { result = cached_results["Genre:" + query]; } else { result = cached_results[query]; } foreach (DatabaseTrackInfo track in result) result[result.IndexOf (track)] = new DatabaseTrackInfo (track); Hyena.Log.DebugFormat ("[LiveRadioBasePlugin\"{0}\"]<RaiseRequestResultRetrieved> result contains {1} entries for query {2}", Name, result.Count, query); } catch (Exception e) { result = null; Hyena.Log.DebugFormat ("[LiveRadioBasePlugin\"{0}\"]<RaiseRequestResultRetrieved> error {1}", Name, e.Message); RaiseErrorReturned ("General Error", e.Message); } OnRequestResultRetrieved (request_type, query, result); }
/// <summary> /// Retrieve and parse a live query on the realradios directory /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; } else { key = query; } if (cached_results.ContainsKey (key)) { return; } string request; if (request_type == LiveRadioRequestType.ByGenre) { request = genres.Find (delegate (Genre g) { return g.Name.Equals(query); } ).Hyperlink; } else { request = base_url + freetext_url + query; } string document = RetrieveHtml(request); if (document != null) ParseHtmlResponse(document, request_type, query); }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseHtmlResponse(string html, LiveRadioRequestType request_type, string query) { int pages = 1; string pagerequest = null; if (html.Contains ("\" title=\"Go to last page\"")) { pagerequest = html.Remove (html.IndexOf ("\" title=\"Go to last page\"")); pagerequest = pagerequest.Substring (pagerequest.LastIndexOf ("\"") + 1); string page = pagerequest.Substring (pagerequest.LastIndexOf ("=") + 1); pagerequest = pagerequest.Remove (pagerequest.IndexOf ("=") + 1); try { pages = Int16.Parse (page); } catch {} } string full_html = null; for (int p = 1; p <= pages; p++) { List<char> badchars = new List<char> (); foreach (char c in html) { if (char.IsControl (c) || char.IsSeparator (c) || char.IsWhiteSpace (c) || char.GetNumericValue (c) == 13 || char.GetNumericValue (c) == 12) if (!badchars.Contains (c)) badchars.Add (c); } foreach (Char c in badchars) html = html.Replace (c, ' '); html = Regex.Replace (html, @"^.*<div class=""station-list"">", "<div>"); html = Regex.Replace (html, @"<img[^>]*>", "<br/>"); if (html.Contains ("ul class=\"pager\"")) { html = Regex.Replace (html, @"<div class=""item-list"">.*$", "<br/>"); } else { html = Regex.Replace (html, @"<div id=""content-footer"".*$", "<div/>"); html = Regex.Replace (html, @"> *<", "><"); html = Regex.Replace (html, @"</div></div></div><div/>", "<br/>"); } html = Regex.Replace (html, @"<br>", "<br/>"); full_html = full_html + html; if (p < pages) { html = RetrieveHtml (pagerequest + (p + 1)); } } html = "<xml>" + full_html + "</xml>"; XmlDocument doc = new XmlDocument (); try { doc.LoadXml (html); } catch (Exception e) { Log.DebugFormat ("[RealRadiosPlugin]<ParseSearchResult> Parse Error: {0}", e.Message); RaiseErrorReturned ("General Error", e.Message); return; } string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; } else { key = query; } cached_results[key] = new List<DatabaseTrackInfo> (); foreach (XmlNode snode in doc.GetElementsByTagName ("div")) { if (snode.Name.Equals ("div") && snode.Attributes != null && snode.Attributes.Count > 0) { try { string location = null; string frequency = null; string title = null; string preurl = null; if (snode.Attributes.GetNamedItem ("class").InnerText.Equals ("station")) { preurl = snode.Attributes.GetNamedItem ("rel").InnerText.Replace ("station-",""); foreach (XmlNode node in snode.ChildNodes) { if (node.Attributes.GetNamedItem ("class").InnerText.Equals ("station-info")) { foreach (XmlNode child in node.SelectNodes ("descendant::*")) { if (child.Name.Equals ("a")) { title = child.InnerText; } else if (child.Name.Equals ("span")) { if (child.Attributes.GetNamedItem ("class").InnerText.Equals ("frequency")) { frequency = child.InnerText; } else if (child.Attributes.GetNamedItem ("class").InnerText.Equals ("location")) { location = child.InnerText; } } } DatabaseTrackInfo new_station = new DatabaseTrackInfo (); new_station.ArtistName = location; new_station.Genre = query; new_station.Comment = frequency; new_station.TrackTitle = title; new_station.PrimarySource = source; new_station.Copyright = preurl; new_station.IsLive = true; cached_results[key].Add (new_station); } } } } catch (Exception e) { Log.DebugFormat ("[RealRadiosPlugin]<ParseSearchResult> XML Parse Error {0}", e.Message); RaiseErrorReturned ("General Error", e.Message); continue; } } } }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseHtmlResponse(string html, LiveRadioRequestType request_type, string query) { int pages = 1; string pagerequest = null; if (html.Contains ("\" title=\"Go to last page\"")) { pagerequest = html.Remove (html.IndexOf ("\" title=\"Go to last page\"")); pagerequest = pagerequest.Substring (pagerequest.LastIndexOf ("\"") + 1); string page = pagerequest.Substring (pagerequest.LastIndexOf ("=") + 1); pagerequest = pagerequest.Remove (pagerequest.IndexOf ("=") + 1); try { pages = Int16.Parse (page); } catch {} Log.DebugFormat ("[RealRadiosPlugin] Parsing Html with {0} pages", page); } string full_html = null; for (int p = 1; p <= pages; p++) { List<char> badchars = new List<char> (); foreach (char c in html) { if (char.IsControl (c) || char.IsSeparator (c) || char.IsWhiteSpace (c) || char.GetNumericValue (c) == 13 || char.GetNumericValue (c) == 12) if (!badchars.Contains (c)) badchars.Add (c); } foreach (Char c in badchars) html = html.Replace (c, ' '); html = Regex.Replace (html, @"^.*<div class=""station-list"">", "<div>"); html = Regex.Replace (html, @"<img[^>]*>", "<br/>"); if (html.Contains ("ul class=\"pager\"")) { html = Regex.Replace (html, @"<div class=""item-list"">.*$", "<br/>"); } else { html = Regex.Replace (html, @"<div id=""content-footer"".*$", "<div/>"); html = Regex.Replace (html, @"> *<", "><"); html = Regex.Replace (html, @"</div></div></div><div/>", "<br/>"); } html = Regex.Replace (html, @"<br>", "<br/>"); full_html = full_html + html; if (p < pages) { Log.DebugFormat ("[RealRadiosPlugin] retrieving page {0}", pagerequest + (p + 1)); html = RetrieveHtml (pagerequest + (p + 1)); } } html = "<xml>" + full_html + "</xml>"; XmlDocument doc = new XmlDocument (); try { doc.LoadXml (html); } catch (Exception e) { Log.DebugFormat ("[RealRadiosPlugin]<ParseSearchResult> Parse Error: {0}", e.Message); RaiseErrorReturned ("General Error", e.Message); Log.DebugFormat ("XML: {0}", html); return; } string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; } else { key = query; } cached_results[key] = new List<DatabaseTrackInfo> (); foreach (XmlNode snode in doc.GetElementsByTagName ("div")) { if (snode.Name.Equals ("div") && snode.Attributes != null && snode.Attributes.Count > 0) { //Log.DebugFormat ("[RealRadiosPlugin] found div with class {0}", node.Attributes.GetNamedItem ("class").InnerText); try { /* <div class="station" rel="station-54437"> <div class="pre"> <span class="index">03</span> </div> <div class="station-info"> <div class="fade"></div> <div class="station-linked favstar medium"> <a href="http://www.realradios.com/north-america/united-states/1club-fm/1club-fm-90s-decade" title="1Club.fm 90s Decade">1Club.fm 90s Decade</a> </div> <div class="meta"> <span class="frequency"></span> <span class="location">United States</span> </div> </div> </div> */ string location = null; string frequency = null; string title = null; //string url = null; string preurl = null; if (snode.Attributes.GetNamedItem ("class").InnerText.Equals ("station")) { preurl = snode.Attributes.GetNamedItem ("rel").InnerText.Replace ("station-",""); foreach (XmlNode node in snode.ChildNodes) { if (node.Attributes.GetNamedItem ("class").InnerText.Equals ("station-info")) { //Log.DebugFormat ("[RealRadiosPlugin] station info found. HasNodes: {0}", node.HasChildNodes); foreach (XmlNode child in node.SelectNodes ("descendant::*")) { //Log.DebugFormat ("[RealRadiosPlugin] {1} node processing: {0}", child.InnerXml, child.Name); if (child.Name.Equals ("a")) { //Log.Debug ("[RealRadiosPlugin] found <a>"); //url = child.Attributes.GetNamedItem ("href").InnerText; title = child.InnerText; } else if (child.Name.Equals ("span")) { if (child.Attributes.GetNamedItem ("class").InnerText.Equals ("frequency")) { //Log.Debug ("[RealRadiosPlugin] found <span> with frequency"); frequency = child.InnerText; } else if (child.Attributes.GetNamedItem ("class").InnerText.Equals ("location")) { //Log.Debug ("[RealRadiosPlugin] found <span> with location"); location = child.InnerText; } } } DatabaseTrackInfo new_station = new DatabaseTrackInfo (); new_station.ArtistName = location; new_station.Genre = query; new_station.Comment = frequency; new_station.TrackTitle = title; new_station.PrimarySource = source; new_station.Copyright = preurl; new_station.IsLive = true; cached_results[key].Add (new_station); } } } } catch (Exception e) { Log.DebugFormat ("[RealRadiosPlugin]<ParseSearchResult> XML Parse Error {0}", e.Message); RaiseErrorReturned ("General Error", e.Message); continue; } } } }
/// <summary> /// Retrieve and parse a live query on the shoutcast directory /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the freetext query or the genre name /// </param> protected override void RetrieveRequest(LiveRadioRequestType request_type, string query) { if (request_type == LiveRadioRequestType.ByGenre) { XmlDocument document = RetrieveXml (base_url + genre_url + query + ".xspf"); if (document != null) ParseXspf (document, new Genre(query)); } else { if (cached_results.ContainsKey (query)) return; string doc = RetrieveHtml (search_url + freetext_request + query); if (!String.IsNullOrEmpty(doc)) ParseSearchResult (doc, query); } }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseXmlResponse(XmlDocument xml_response, LiveRadioRequestType request_type, string query) { string session = GetSession(); List <string> pages = new List <string> (); pages.Add(null); XmlNodeList pagination_nodes = xml_response.GetElementsByTagName("PAGINATION_PAGES"); foreach (XmlNode node in pagination_nodes) { string url = null; bool url_valid = false; XmlNodeList page_nodes = node.ChildNodes; foreach (XmlNode page_node in page_nodes) { try { if (page_node.LocalName.Equals("PAGINATION_DESC") && !page_node.InnerText.Trim().Equals("1") && !page_node.InnerText.Trim().Equals("Next")) { url_valid = true; } if (page_node.LocalName.Equals("PAGINATION_LINK")) { url = page_node.InnerText; } } catch (Exception e) { Log.Warning("[Live365Plugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned("XML Parse Error", e.Message); return; } } if (!String.IsNullOrEmpty(url) && url_valid) { pages.Add(url); } } string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; if (!cached_results.ContainsKey(key)) { cached_results[key] = new List <DatabaseTrackInfo> (); } } else { key = query; if (!cached_results.ContainsKey(key)) { cached_results[key] = new List <DatabaseTrackInfo> (); } } cached_results[key].Clear(); foreach (string page in pages) { XmlDocument doc; if (String.IsNullOrEmpty(page)) { doc = xml_response; } else { doc = RetrieveXml(page); } XmlNodeList XML_station_nodes = doc.GetElementsByTagName("LIVE365_STATION"); foreach (XmlNode node in XML_station_nodes) { string name = null; string access = null; string ex_id = null; string url = null; string broadcaster = null; string description = null; string keywords = null; string genre = null; string bitrate = null; string rating = null; string status = null; string location = null; XmlNodeList childnodes = node.ChildNodes; foreach (XmlNode child in childnodes) { try { if (child.LocalName.Equals("STATION_ADDRESS")) { url = child.InnerText; } else if (child.LocalName.Equals("STATION_ID")) { ex_id = child.InnerText; } else if (child.LocalName.Equals("STATION_BROADCASTER")) { broadcaster = child.InnerText; } else if (child.LocalName.Equals("STATION_TITLE")) { name = child.InnerText; } else if (child.LocalName.Equals("STATION_DESCRIPTION")) { description = child.InnerText; } else if (child.LocalName.Equals("STATION_KEYWORDS")) { keywords = child.InnerText; } else if (child.LocalName.Equals("STATION_GENRE")) { genre = child.InnerText; } else if (child.LocalName.Equals("STATION_CONNECTION")) { bitrate = child.InnerText; } else if (child.LocalName.Equals("STATION_RATING")) { rating = child.InnerText; } else if (child.LocalName.Equals("STATION_STATUS")) { status = child.InnerText; } else if (child.LocalName.Equals("LISTENER_ACCESS")) { access = child.InnerText; } else if (child.LocalName.Equals("STATION_LOCATION")) { location = child.InnerText; } } catch (Exception e) { Log.Warning("[Live365Plugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned("General Error", e.Message); continue; } } int bitrate_int; int id_int; int rating_int; if (!String.IsNullOrEmpty(access) && !String.IsNullOrEmpty(status) && (access.Equals("PUBLIC") || UseCredentials) && status.Equals("OK")) { DatabaseTrackInfo new_station = new DatabaseTrackInfo(); if (UseCredentials) { url = url.Replace(replace_url, playlist_url); url += session; } new_station.Uri = new SafeUri(url); new_station.ArtistName = broadcaster; new_station.Genre = genre; new_station.TrackTitle = name; new_station.Comment = description + location + keywords; Int32.TryParse(rating.Trim(), out rating_int); new_station.Rating = rating_int; Int32.TryParse(ex_id.Trim(), out id_int); new_station.ExternalId = id_int; new_station.PrimarySource = source; new_station.IsLive = true; Int32.TryParse(bitrate.Trim(), out bitrate_int); new_station.BitRate = bitrate_int; new_station.IsLive = true; cached_results[key].Add(new_station); } } } }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseHtmlResponse(string html, LiveRadioRequestType request_type, string query) { int pages = 1; string pagerequest = null; if (html.Contains("\" title=\"Go to last page\"")) { pagerequest = html.Remove(html.IndexOf("\" title=\"Go to last page\"")); pagerequest = pagerequest.Substring(pagerequest.LastIndexOf("\"") + 1); string page = pagerequest.Substring(pagerequest.LastIndexOf("=") + 1); pagerequest = pagerequest.Remove(pagerequest.IndexOf("=") + 1); try { pages = Int16.Parse(page); } catch {} } string full_html = null; for (int p = 1; p <= pages; p++) { List <char> badchars = new List <char> (); foreach (char c in html) { if (char.IsControl(c) || char.IsSeparator(c) || char.IsWhiteSpace(c) || char.GetNumericValue(c) == 13 || char.GetNumericValue(c) == 12) { if (!badchars.Contains(c)) { badchars.Add(c); } } } foreach (Char c in badchars) { html = html.Replace(c, ' '); } html = Regex.Replace(html, @"^.*<div class=""station-list"">", "<div>"); html = Regex.Replace(html, @"<img[^>]*>", "<br/>"); if (html.Contains("ul class=\"pager\"")) { html = Regex.Replace(html, @"<div class=""item-list"">.*$", "<br/>"); } else { html = Regex.Replace(html, @"<div id=""content-footer"".*$", "<div/>"); html = Regex.Replace(html, @"> *<", "><"); html = Regex.Replace(html, @"</div></div></div><div/>", "<br/>"); } html = Regex.Replace(html, @"<br>", "<br/>"); full_html = full_html + html; if (p < pages) { html = RetrieveHtml(pagerequest + (p + 1)); } } html = "<xml>" + full_html + "</xml>"; XmlDocument doc = new XmlDocument(); try { doc.LoadXml(html); } catch (Exception e) { Log.DebugFormat("[RealRadiosPlugin]<ParseSearchResult> Parse Error: {0}", e.Message); RaiseErrorReturned("General Error", e.Message); return; } string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; } else { key = query; } cached_results[key] = new List <DatabaseTrackInfo> (); foreach (XmlNode snode in doc.GetElementsByTagName("div")) { if (snode.Name.Equals("div") && snode.Attributes != null && snode.Attributes.Count > 0) { try { string location = null; string frequency = null; string title = null; string preurl = null; if (snode.Attributes.GetNamedItem("class").InnerText.Equals("station")) { preurl = snode.Attributes.GetNamedItem("rel").InnerText.Replace("station-", ""); foreach (XmlNode node in snode.ChildNodes) { if (node.Attributes.GetNamedItem("class").InnerText.Equals("station-info")) { foreach (XmlNode child in node.SelectNodes("descendant::*")) { if (child.Name.Equals("a")) { title = child.InnerText; } else if (child.Name.Equals("span")) { if (child.Attributes.GetNamedItem("class").InnerText.Equals("frequency")) { frequency = child.InnerText; } else if (child.Attributes.GetNamedItem("class").InnerText.Equals("location")) { location = child.InnerText; } } } DatabaseTrackInfo new_station = new DatabaseTrackInfo(); new_station.ArtistName = location; new_station.Genre = query; new_station.Comment = frequency; new_station.TrackTitle = title; new_station.PrimarySource = source; new_station.Copyright = preurl; new_station.IsLive = true; cached_results[key].Add(new_station); } } } } catch (Exception e) { Log.DebugFormat("[RealRadiosPlugin]<ParseSearchResult> XML Parse Error {0}", e.Message); RaiseErrorReturned("General Error", e.Message); continue; } } } }
/// <summary> /// Method to invoke the RequestResultRetrieved event /// </summary> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the original request type /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the original freetext query or the original genre name /// </param> /// <param name="result"> /// A <see cref="List<DatabaseTrackInfo>"/> -- the resulting list of DatabaseTrackInfo objects for the query /// </param> protected void OnRequestResultRetrieved(LiveRadioRequestType request_type, string query, List<DatabaseTrackInfo> result) { RequestResultRetrievedEventHandler handler = RequestResultRetrieved; if (handler != null) { handler (this, query, request_type, result); } }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseXmlResponse(XmlDocument xml_response, LiveRadioRequestType request_type, string query) { string tunein_url = ""; XmlNodeList XML_tunein_nodes = xml_response.GetElementsByTagName ("tunein"); foreach (XmlNode node in XML_tunein_nodes) { XmlAttributeCollection xml_attributes = node.Attributes; try { tunein_url = xml_attributes.GetNamedItem("base").InnerText; break; } catch (Exception e) { Log.Warning ("[ShoutCastPlugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned ("XML Parse Error", e.Message); return; } } XmlNodeList XML_station_nodes = xml_response.GetElementsByTagName ("station"); string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; if (!cached_results.ContainsKey (key)) { cached_results[key] = new List<DatabaseTrackInfo> (XML_station_nodes.Count); } } else { key = query; if (!cached_results.ContainsKey (key)) { cached_results[key] = new List<DatabaseTrackInfo> (XML_station_nodes.Count); } } cached_results[key].Clear (); foreach (XmlNode node in XML_station_nodes) { XmlAttributeCollection xml_attributes = node.Attributes; try { string name = xml_attributes.GetNamedItem ("name").InnerText; string media_type = xml_attributes.GetNamedItem ("mt").InnerText; string id = xml_attributes.GetNamedItem ("id").InnerText; string genre = xml_attributes.GetNamedItem ("genre").InnerText; string now_playing = xml_attributes.GetNamedItem ("ct").InnerText; string bitrate = xml_attributes.GetNamedItem ("br").InnerText; int id_int; int bitrate_int; if (!Int32.TryParse (id.Trim (), out id_int)) { continue; //Something wrong with id, skip this } DatabaseTrackInfo new_station = new DatabaseTrackInfo (); new_station.Uri = new SafeUri (play_url + tunein_url + "?id=" + id); new_station.ArtistName = "www.shoutcast.com"; new_station.Genre = genre; new_station.TrackTitle = name; new_station.Comment = now_playing; new_station.AlbumTitle = now_playing; new_station.MimeType = media_type; new_station.ExternalId = id_int; new_station.PrimarySource = source; new_station.IsLive = true; Int32.TryParse (bitrate.Trim (), out bitrate_int); new_station.BitRate = bitrate_int; new_station.IsLive = true; cached_results[key].Add (new_station); } catch (Exception e) { Log.Warning ("[ShoutCastPlugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned ("XML Parse Error", e.Message); continue; } } }