diff --git a/src/Hqub.MusicBrainz.API/Configuration.cs b/src/Hqub.MusicBrainz.API/Configuration.cs new file mode 100644 index 000000000..f8b1da755 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Configuration.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace Hqub.MusicBrainz.API +{ + public static class Configuration + { + static Configuration() + { + GenerateCommunicationThrow = true; + Proxy = null; + UserAgent = "Hqub.MusicBrainz/2.0"; + } + + /// + /// If true, then all exceptions for http-requests to MusicBrainz (from class WebRequestHelper) will + /// throw up. Otherwise they will be suppressed. + /// + public static bool GenerateCommunicationThrow { get; set; } + + + /// + /// Gets or sets a used to query the webservice. + /// + public static IWebProxy Proxy { get; set; } + + /// + /// Allow set cutstom user agent string. + /// + public static string UserAgent { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Artist.cs b/src/Hqub.MusicBrainz.API/Entities/Artist.cs new file mode 100644 index 000000000..8691df73e --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Artist.cs @@ -0,0 +1,204 @@ +using System; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; +using Hqub.MusicBrainz.API.Entities.Metadata; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("artist", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Artist : Entity + { + public const string EntityName = "artist"; + + #region Properties + + /// + /// Gets or sets the score (only available in search results). + /// + [XmlAttribute("score", Namespace = "http://musicbrainz.org/ns/ext#-2.0")] + public int Score { get; set; } + + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the type. + /// + [XmlAttribute("type")] + public string Type { get; set; } + + /// + /// Gets or sets the name. + /// + [XmlElement("name")] + public string Name { get; set; } + + /// + /// Gets or sets the sort name. + /// + [XmlElement("sort-name")] + public string SortName { get; set; } + + /// + /// Gets or sets the gender. + /// + [XmlElement("gender")] + public string Gender { get; set; } + + /// + /// Gets or sets the life-span. + /// + [XmlElement("life-span")] + public LifeSpanNode LifeSpan { get; set; } + + /// + /// Gets or sets the country. + /// + [XmlElement("country")] + public string Country { get; set; } + + /// + /// Gets or sets the disambiguation. + /// + [XmlElement("disambiguation")] + public string Disambiguation { get; set; } + + /// + /// Gets or sets the rating. + /// + [XmlElement("rating")] + public Rating Rating { get; set; } + + #endregion + + #region Subqueries + + [XmlElement("recording-list")] + public RecordingList Recordings { get; set; } + + [XmlElement("release-group-list")] + public ReleaseGroupList ReleaseGroups { get; set; } + + [XmlElement("release-list")] + public ReleaseList ReleaseLists { get; set; } + + [XmlElement("relation-list")] + public RelationList RelationLists { get; set; } + + [XmlElement("work-list")] + public WorkList Works { get; set; } + + [XmlElement("tag-list")] + public TagList Tags { get; set; } + + #endregion + + #region Static Methods + + [Obsolete("Use GetAsync() method.")] + public static Artist Get(string id, params string[] inc) + { + return GetAsync(EntityName, id, inc).Result; + } + + [Obsolete("Use SearchAsync() method.")] + public static ArtistList Search(string query, int limit = 25, int offset = 0) + { + return SearchAsync(EntityName, + query, limit, offset).Result.Collection; + } + + [Obsolete("Use BrowseAsync() method.")] + public static ArtistList Browse(string relatedEntity, string value, int limit = 25, int offset = 0, params string[] inc) + { + return BrowseAsync(EntityName, + relatedEntity, value, limit, offset, inc).Result.Collection; + } + + /// + /// Lookup an artist in the MusicBrainz database. + /// + /// The artist MusicBrainz id. + /// A list of entities to include (subqueries). + /// + public async static Task GetAsync(string id, params string[] inc) + { + return await GetAsync(EntityName, id, inc); + } + + /// + /// Search for an artist in the MusicBrainz database, matching the given query. + /// + /// The query string. + /// The maximum number of artists to return (default = 25). + /// The offset to the artists list (enables paging, default = 0). + /// + public async static Task SearchAsync(string query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query, limit, offset)).Collection; + } + + /// + /// Search for an artist in the MusicBrainz database, matching the given query. + /// + /// The query parameters. + /// The maximum number of artists to return (default = 25). + /// The offset to the artists list (enables paging, default = 0). + /// + public async static Task SearchAsync(QueryParameters query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query.ToString(), limit, offset)).Collection; + } + + /// + /// Browse all the artists in the MusicBrainz database, which are directly linked to the + /// entity with given id. + /// + /// The name of the related entity. + /// The id of the related entity. + /// The maximum number of artists to return (default = 25). + /// The offset to the artists list (enables paging, default = 0). + /// A list of entities to include (subqueries). + /// + public async static Task BrowseAsync(string entity, string id, int limit = 25, int offset = 0, params string[] inc) + { + return (await BrowseAsync(EntityName, entity, id, + limit, offset, inc)).Collection; + } + + #endregion + } + + #region Include entities + + [XmlRoot("life-span", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class LifeSpanNode + { + /// + /// Gets or sets the begin date. + /// + [XmlElement("begin")] + public string Begin { get; set; } + + /// + /// Gets or sets the end date. + /// + [XmlElement("end")] + public string End { get; set; } + + /// + /// Gets or sets a value indicating whether the life-span ended or not. + /// + [XmlElement("ended")] + public bool Ended { get; set; } + } + + #endregion + +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/ArtistList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/ArtistList.cs new file mode 100644 index 000000000..5fcf3ab9a --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/ArtistList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("artist-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ArtistList : BaseList + { + /// + /// Gets or sets the list of artists. + /// + [XmlElement("artist")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/BaseList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/BaseList.cs new file mode 100644 index 000000000..804a87727 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/BaseList.cs @@ -0,0 +1,25 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + public class BaseList + { + /// + /// Gets or sets the total list items count. + /// + /// + /// This might be different form the actual list items count. If the list was + /// generated from a search request, this property will return the total number + /// of available items (on the server), while the number of returned items is + /// limited by the requests 'limit' parameter (default = 25). + /// + [XmlAttribute("count")] + public int QueryCount { get; set; } + + /// + /// Gets or sets the list offset (only available in search requests). + /// + [XmlAttribute("offset")] + public int QueryOffset { get; set; } + } +} \ No newline at end of file diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/MediumList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/MediumList.cs new file mode 100644 index 000000000..54dfe0d51 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/MediumList.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("medium-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class MediumList : BaseList + { + /// + /// Gets or sets the medium track count. + /// + /// + /// Only available in the result of a release search (???). + /// + [XmlElement(ElementName = "track-count")] + public int TrackCount { get; set; } + + /// + /// Gets or sets the list of mediums. + /// + [XmlElement("medium")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/RecordingList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/RecordingList.cs new file mode 100644 index 000000000..d2f5da68d --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/RecordingList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("recording-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class RecordingList : BaseList + { + /// + /// Gets or sets the list of recordings. + /// + [XmlElement("recording")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/RelationList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/RelationList.cs new file mode 100644 index 000000000..8afa952ed --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/RelationList.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("relation-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class RelationList : BaseList + { + /// + /// Gets or sets the relation target type. + /// + [XmlAttribute("target-type")] + public string TargetType { get; set; } + + /// + /// Gets or sets the list of relations. + /// + [XmlElement("relation")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/ReleaseGroupList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/ReleaseGroupList.cs new file mode 100644 index 000000000..b436cf3c6 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/ReleaseGroupList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("recording-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ReleaseGroupList : BaseList + { + /// + /// Gets or sets the list of release-groups. + /// + [XmlElement("release-group")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/ReleaseList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/ReleaseList.cs new file mode 100644 index 000000000..d8baa7514 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/ReleaseList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("release-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ReleaseList : BaseList + { + /// + /// Gets or sets the list of releases. + /// + [XmlElement("release")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/TagList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/TagList.cs new file mode 100644 index 000000000..759df8693 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/TagList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("tag-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class TagList : BaseList + { + /// + /// Gets or sets the list of tags. + /// + [XmlElement("tag")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/TrackList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/TrackList.cs new file mode 100644 index 000000000..49db502fc --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/TrackList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("track-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class TrackList : BaseList + { + /// + /// Gets or sets the list of tracks. + /// + [XmlElement("track")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Collections/WorkList.cs b/src/Hqub.MusicBrainz.API/Entities/Collections/WorkList.cs new file mode 100644 index 000000000..d7476a490 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Collections/WorkList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities.Collections +{ + [XmlRoot("work-list", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class WorkList : BaseList + { + /// + /// Gets or sets the list of works. + /// + [XmlElement("work")] + public List Items { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/CoverArtArchive.cs b/src/Hqub.MusicBrainz.API/Entities/CoverArtArchive.cs new file mode 100644 index 000000000..447fd86cc --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/CoverArtArchive.cs @@ -0,0 +1,39 @@ +using System; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("cover-art-archive", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class CoverArtArchive + { + /// + /// Gets or sets a value indicating whether artwork is available or not. + /// + [XmlElement("artwork")] + public bool Artwork { get; set; } + + /// + /// Gets or sets the count. + /// + [XmlElement("count")] + public int Count { get; set; } + + /// + /// Gets or sets a value indicating whether a front crover is available or not. + /// + [XmlElement("front")] + public bool Front { get; set; } + + /// + /// Gets or sets a value indicating whether a back crover is available or not. + /// + [XmlElement("back")] + public bool Back { get; set; } + + public static Uri GetCoverArtUri(string releaseId) + { + string url = "http://coverartarchive.org/release/" + releaseId + "/front-250.jpg"; + return new Uri(url, UriKind.RelativeOrAbsolute); + } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Entity.cs b/src/Hqub.MusicBrainz.API/Entities/Entity.cs new file mode 100644 index 000000000..fa81969a0 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Entity.cs @@ -0,0 +1,87 @@ +using System; +using System.Threading.Tasks; +using Hqub.MusicBrainz.API.Entities.Metadata; + +namespace Hqub.MusicBrainz.API.Entities +{ + /// + /// Base class for any entity returned by the MusicBrainz XML webservice. + /// + public abstract class Entity + { + private static string CreateIncludeQuery(string[] inc) + { + return string.Join("+", inc); + } + + /// + /// Sends a lookup request to the webservice. + /// + /// Any type derived from . + /// The name of the XML entity to lookup. + /// The MusicBrainz id of the entity. + /// A list of entities to include (subqueries). + /// + protected async static Task GetAsync(string entity, string id, params string[] inc) where T : Entity + { + if (string.IsNullOrEmpty(entity)) + { + throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "entity")); + } + + if (string.IsNullOrEmpty(id)) + { + throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "id")); + } + + return await WebRequestHelper.GetAsync(WebRequestHelper.CreateLookupUrl(entity, id, CreateIncludeQuery(inc))); + } + + /// + /// Sends a search request to the webservice. + /// + /// Any type derived from . + /// The name of the XML entity to search for. + /// The query string. + /// The number of items to return (default = 25). + /// The offset to the items list (enables paging, default = 0). + /// + protected async static Task SearchAsync(string entity, string query, int limit = 25, int offset = 0) where T : MetadataWrapper + { + if (string.IsNullOrEmpty(entity)) + { + throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "entity")); + } + + if (string.IsNullOrEmpty(query)) + { + throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "query")); + } + + return await WebRequestHelper.GetAsync(WebRequestHelper.CreateSearchTemplate(entity, + query, limit, offset), withoutMetadata: false); + } + + /// + /// Sends a browse request to the webservice. + /// + /// Any type derived from . + /// The name of the XML entity to browse. + /// + /// + /// The number of items to return (default = 25). + /// The offset to the items list (enables paging, default = 0). + /// A list of entities to include (subqueries). + /// + protected async static Task BrowseAsync(string entity, string relatedEntity, string relatedEntityId, int limit, int offset, params string[] inc) where T : Entity + { + if (string.IsNullOrEmpty(entity)) + { + throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "entity")); + } + + return await WebRequestHelper.GetAsync(WebRequestHelper.CreateBrowseTemplate(entity, + relatedEntity, relatedEntityId, limit, offset, CreateIncludeQuery(inc)), withoutMetadata: false); + } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Include/ArtistIncludeEntityHelper.cs b/src/Hqub.MusicBrainz.API/Entities/Include/ArtistIncludeEntityHelper.cs new file mode 100644 index 000000000..076ec955b --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Include/ArtistIncludeEntityHelper.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Hqub.MusicBrainz.API.Entities.Include +{ + public static class ArtistIncludeEntityHelper + { + public const string Recordings = "recordings"; + public const string Releases = "releases"; + public const string ReleaseGroups = "release-groups"; + public const string Works = "works"; + public const string Tags = "tags"; + public const string Ratings = "ratings"; + + // Relations +// public const string ArtistRelation = "artist-rels"; +// public const string LabelRelation = "label-rels"; +// public const string RecordingRelation = "recording-rels"; +// public const string ReleaseRelation = "release-rels"; +// public const string ReleaseGroupRelation = "release-group-rels"; + public const string UrlRelation = "url-rels"; +// public const string WorkRelation = "work-rels"; + + + public static bool Check(string incEntity) + { + switch (incEntity) + { + case Recordings: + case Releases: + case ReleaseGroups: + case Works: + case Tags: + case Ratings: + return true; + default: + return false; + } + } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Label.cs b/src/Hqub.MusicBrainz.API/Entities/Label.cs new file mode 100644 index 000000000..17dc83723 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Label.cs @@ -0,0 +1,20 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("label")] + public class Label + { + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the name. + /// + [XmlElement("name")] + public string Name { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/LabelInfo.cs b/src/Hqub.MusicBrainz.API/Entities/LabelInfo.cs new file mode 100644 index 000000000..c9b61527d --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/LabelInfo.cs @@ -0,0 +1,20 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("label-info")] + public class LabelInfo + { + /// + /// Gets or sets the catalog-number. + /// + [XmlElement("catalog-number")] + public string CatalogNumber { get; set; } + + /// + /// Gets or sets the label. + /// + [XmlElement("label")] + public Label Label { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Medium.cs b/src/Hqub.MusicBrainz.API/Entities/Medium.cs new file mode 100644 index 000000000..06c0dc729 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Medium.cs @@ -0,0 +1,36 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("medium")] + public class Medium + { + /// + /// Gets or sets the format. + /// + [XmlElement("format")] + public string Format { get; set; } + + /// + /// Gets or sets the disc-list. + /// + [XmlElement("disc-list")] + public DiskList Disks { get; set; } + + /// + /// Gets or sets the track-list. + /// + [XmlElement("track-list")] + public Collections.TrackList Tracks { get; set; } + } + + [XmlRoot("disk-list")] + public class DiskList + { + /// + /// Gets or sets the count. + /// + [XmlAttribute("count")] + public int Count { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Metadata.cs b/src/Hqub.MusicBrainz.API/Entities/Metadata.cs new file mode 100644 index 000000000..6f10af0fc --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Metadata.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Hqub.MusicBrainz.API.Entities +{ + public abstract class MetadataWrapper : Entity + { + + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Metadata/ArtistMetadata.cs b/src/Hqub.MusicBrainz.API/Entities/Metadata/ArtistMetadata.cs new file mode 100644 index 000000000..44398809b --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Metadata/ArtistMetadata.cs @@ -0,0 +1,15 @@ +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; + +namespace Hqub.MusicBrainz.API.Entities.Metadata +{ + [XmlRoot("metadata", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ArtistMetadata : MetadataWrapper + { + /// + /// Gets or sets the artist-list collection. + /// + [XmlElement("artist-list")] + public ArtistList Collection { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Metadata/RecordingMetadata.cs b/src/Hqub.MusicBrainz.API/Entities/Metadata/RecordingMetadata.cs new file mode 100644 index 000000000..265a571b4 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Metadata/RecordingMetadata.cs @@ -0,0 +1,15 @@ +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; + +namespace Hqub.MusicBrainz.API.Entities.Metadata +{ + [XmlRoot("metadata", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class RecordingMetadata : MetadataWrapper + { + /// + /// Gets or sets the recording-list collection. + /// + [XmlElement("recording-list")] + public RecordingList Collection { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Metadata/ReleaseGroupMetadata.cs b/src/Hqub.MusicBrainz.API/Entities/Metadata/ReleaseGroupMetadata.cs new file mode 100644 index 000000000..8dfae506e --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Metadata/ReleaseGroupMetadata.cs @@ -0,0 +1,15 @@ +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; + +namespace Hqub.MusicBrainz.API.Entities.Metadata +{ + [XmlRoot("metadata", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ReleaseGroupMetadata : MetadataWrapper + { + /// + /// Gets or sets the release-group collection. + /// + [XmlElement("release-group-list")] + public ReleaseGroupList Collection { get; set; } + } +} \ No newline at end of file diff --git a/src/Hqub.MusicBrainz.API/Entities/Metadata/ReleaseMetadata.cs b/src/Hqub.MusicBrainz.API/Entities/Metadata/ReleaseMetadata.cs new file mode 100644 index 000000000..f38ab3b9b --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Metadata/ReleaseMetadata.cs @@ -0,0 +1,15 @@ +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; + +namespace Hqub.MusicBrainz.API.Entities.Metadata +{ + [XmlRoot("metadata", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ReleaseMetadata : MetadataWrapper + { + /// + /// Gets or sets the release-list collection. + /// + [XmlElement("release-list")] + public ReleaseList Collection { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/NameCredit.cs b/src/Hqub.MusicBrainz.API/Entities/NameCredit.cs new file mode 100644 index 000000000..928328884 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/NameCredit.cs @@ -0,0 +1,20 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("name-credit")] + public class NameCredit + { + /// + /// Gets or sets the joinphrase. + /// + [XmlAttribute("joinphrase")] + public string JoinPhrase { get; set; } + + /// + /// Gets or sets the artist. + /// + [XmlElement("artist")] + public Artist Artist { get; set; } + } +} \ No newline at end of file diff --git a/src/Hqub.MusicBrainz.API/Entities/Rating.cs b/src/Hqub.MusicBrainz.API/Entities/Rating.cs new file mode 100644 index 000000000..83107b7df --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Rating.cs @@ -0,0 +1,20 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("rating", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Rating + { + /// + /// Gets or sets the votes-count. + /// + [XmlAttribute("votes-count")] + public int VotesCount { get; set; } + + /// + /// Gets or sets the rating value. + /// + [XmlText] + public double Value { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Recording.cs b/src/Hqub.MusicBrainz.API/Entities/Recording.cs new file mode 100644 index 000000000..9e8072d96 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Recording.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; +using Hqub.MusicBrainz.API.Entities.Metadata; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("recording", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Recording : Entity + { + public const string EntityName = "recording"; + + #region Properties + + /// + /// Gets or sets the score (only available in search results). + /// + [XmlAttribute("score", Namespace = "http://musicbrainz.org/ns/ext#-2.0")] + public int Score { get; set; } + + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the title. + /// + [XmlElement("title")] + public string Title { get; set; } + + /// + /// Gets or sets the length. + /// + [XmlElement("length")] + public int Length { get; set; } + + /// + /// Gets or sets the disambiguation. + /// + [XmlElement("disambiguation")] + public string Disambiguation { get; set; } + + #endregion + + #region Include + + [XmlElement("tag-list")] + public TagList Tags { get; set; } + + [XmlArray("artist-credit")] + [XmlArrayItem("name-credit")] + public List Credits { get; set; } + + [XmlElement("release-list")] + public ReleaseList Releases { get; set; } + + #endregion + + #region Static methods + + [Obsolete("Use GetAsync() method.")] + public static Recording Get(string id, params string[] inc) + { + return GetAsync(EntityName, id, inc).Result; + } + + [Obsolete("Use SearchAsync() method.")] + public static RecordingList Search(string query, int limit = 25, int offset = 0) + { + return SearchAsync(EntityName, + query, limit, offset).Result.Collection; + } + + [Obsolete("Use BrowseAsync() method.")] + public static RecordingList Browse(string relatedEntity, string value, int limit = 25, int offset = 0, params string[] inc) + { + return BrowseAsync(EntityName, + relatedEntity, value, limit, offset, inc).Result.Collection; + } + + /// + /// Lookup an recording in the MusicBrainz database. + /// + /// The recording MusicBrainz id. + /// A list of entities to include (subqueries). + /// + public async static Task GetAsync(string id, params string[] inc) + { + return await GetAsync(EntityName, id, inc); + } + + /// + /// Search for an recording in the MusicBrainz database, matching the given query. + /// + /// The query string. + /// The maximum number of recordings to return (default = 25). + /// The offset to the recordings list (enables paging, default = 0). + /// + public async static Task SearchAsync(string query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query, limit, offset)).Collection; + } + + /// + /// Search for an recording in the MusicBrainz database, matching the given query. + /// + /// The query parameters. + /// The maximum number of recordings to return (default = 25). + /// The offset to the recordings list (enables paging, default = 0). + /// + public async static Task SearchAsync(QueryParameters query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query.ToString(), limit, offset)).Collection; + } + + /// + /// Browse all the recordings in the MusicBrainz database, which are directly linked to the + /// entity with given id. + /// + /// The name of the related entity. + /// The id of the related entity. + /// The maximum number of recordings to return (default = 25). + /// The offset to the recordings list (enables paging, default = 0). + /// A list of entities to include (subqueries). + /// + public async static Task BrowseAsync(string entity, string id, int limit = 25, int offset = 0, params string[] inc) + { + return (await BrowseAsync(EntityName, + entity, id, limit, offset, inc)).Collection; + } + + #endregion + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Relation.cs b/src/Hqub.MusicBrainz.API/Entities/Relation.cs new file mode 100644 index 000000000..00ff2c6ec --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Relation.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; +using Hqub.MusicBrainz.API.Entities.Metadata; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("relation", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Relation : Entity + { + public const string EntityName = "relation"; + + /// + /// Gets or sets the relation type. + /// + [XmlAttribute("type")] + public string Type { get; set; } + + /// + /// Gets or sets the relation type ID. + /// + [XmlAttribute("type-id")] + public string TypeId { get; set; } + + /// + /// Gets or sets the relation target. + /// + [XmlElement("target")] + public string Target { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Release.cs b/src/Hqub.MusicBrainz.API/Entities/Release.cs new file mode 100644 index 000000000..3be01cca6 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Release.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; +using Hqub.MusicBrainz.API.Entities.Metadata; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("release", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Release : Entity + { + public const string EntityName = "release"; + + #region Properties + + /// + /// Gets or sets the score (only available in search results). + /// + [XmlAttribute("score", Namespace = "http://musicbrainz.org/ns/ext#-2.0")] + public int Score { get; set; } + + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the title. + /// + [XmlElement("title")] + public string Title { get; set; } + + /// + /// Gets or sets the status. + /// + [XmlElement("status")] + public string Status { get; set; } + + /// + /// Gets or sets the quality. + /// + [XmlElement("quality")] + public string Quality { get; set; } + + /// + /// Gets or sets the text-representation. + /// + [XmlElement("text-representation")] + public TextRepresentation TextRepresentation { get; set; } + + /// + /// Gets or sets the date. + /// + [XmlElement("date")] + public string Date { get; set; } + + /// + /// Gets or sets the country. + /// + [XmlElement("country")] + public string Country { get; set; } + + /// + /// Gets or sets the barcode. + /// + [XmlElement("barcode")] + public string Barcode { get; set; } + + /// + /// Gets or sets the release-group. + /// + [XmlElement("release-group")] + public ReleaseGroup ReleaseGroup { get; set; } + + /// + /// Gets or sets the cover-art-archive. + /// + [XmlElement("cover-art-archive")] + public CoverArtArchive CoverArtArchive { get; set; } + + #endregion + + #region Subqueries + + [XmlArray("artist-credit")] + [XmlArrayItem("name-credit")] + public List Credits { get; set; } + + [XmlArray("label-info-list")] + [XmlArrayItem("label-info")] + public List Labels { get; set; } + + [XmlElement("medium-list")] + public Collections.MediumList MediumList { get; set; } + + #endregion + + #region Static Methods + + [Obsolete("Use GetAsync() method.")] + public static Release Get(string id, params string[] inc) + { + return GetAsync(EntityName, id, inc).Result; + } + + [Obsolete("Use SearchAsync() method.")] + public static ReleaseList Search(string query, int limit = 25, int offset = 0) + { + return SearchAsync(EntityName, + query, limit, offset).Result.Collection; + } + + /// + /// Lookup a release in the MusicBrainz database. + /// + /// The release MusicBrainz id. + /// A list of entities to include (subqueries). + /// + public async static Task GetAsync(string id, params string[] inc) + { + return await GetAsync(EntityName, id, inc); + } + + /// + /// Search for a release in the MusicBrainz database, matching the given query. + /// + /// The query string. + /// The maximum number of releases to return (default = 25). + /// The offset to the releases list (enables paging, default = 0). + /// + public async static Task SearchAsync(string query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query, limit, offset)).Collection; + } + + /// + /// Search for a release in the MusicBrainz database, matching the given query. + /// + /// The query parameters. + /// The maximum number of releases to return (default = 25). + /// The offset to the releases list (enables paging, default = 0). + /// + public async static Task SearchAsync(QueryParameters query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query.ToString(), limit, offset)).Collection; + } + + /// + /// Browse all the releases in the MusicBrainz database, which are directly linked to the + /// entity with given id. + /// + /// The name of the related entity. + /// The id of the related entity. + /// The maximum number of releases to return (default = 25). + /// The offset to the releases list (enables paging, default = 0). + /// A list of entities to include (subqueries). + /// + public static async Task BrowseAsync(string entity, string id, int limit = 25, + int offset = 0, params string[] inc) + { + return (await BrowseAsync(EntityName, + entity, id, limit, offset, inc)).Collection; + } + + #endregion + } + + [XmlType(Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + [XmlRoot("text-representation", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class TextRepresentation + { + /// + /// Gets or sets the language. + /// + [XmlElement("language")] + public string Language { get; set; } + + /// + /// Gets or sets the script. + /// + [XmlElement("script")] + public string Script { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/ReleaseGroup.cs b/src/Hqub.MusicBrainz.API/Entities/ReleaseGroup.cs new file mode 100644 index 000000000..e5cf2f48a --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/ReleaseGroup.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Hqub.MusicBrainz.API.Entities.Collections; +using Hqub.MusicBrainz.API.Entities.Metadata; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("release-group", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class ReleaseGroup : Entity + { + public const string EntityName = "release-group"; + + #region Properties + + /// + /// Gets or sets the score (only available in search results). + /// + [XmlAttribute("score", Namespace = "http://musicbrainz.org/ns/ext#-2.0")] + public int Score { get; set; } + + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the type (like album, single or ep). + /// + [XmlAttribute("type")] + public string Type { get; set; } + + /// + /// Gets or sets the title. + /// + [XmlElement("title")] + public string Title { get; set; } + + /// + /// Gets or sets the first release date. + /// + [XmlElement("first-release-date")] + public string FirstReleaseDate { get; set; } + + /// + /// Gets or sets the primary type. + /// + [XmlElement("primary-type")] + public string PrimaryType { get; set; } + + /// + /// Gets or sets the rating". + /// + [XmlElement("rating")] + public Rating Rating { get; set; } + + /// + /// Gets or sets the tag-list. + /// + [XmlElement("tag-list")] + public TagList Tags { get; set; } + + #endregion + + #region Subqueries + + [XmlArray("artist-credit")] + [XmlArrayItem("name-credit")] + public List Credits { get; set; } + + [XmlArray("release-list")] + [XmlArrayItem("release")] + public List Releases { get; set; } + + #endregion + + #region Static Methods + + [Obsolete("Use GetAsync() method.")] + public static ReleaseGroup Get(string id, params string[] inc) + { + return GetAsync(EntityName, id, inc).Result; + } + + [Obsolete("Use SearchAsync() method.")] + public static ReleaseGroupList Search(string query, int limit = 25, int offset = 0) + { + return SearchAsync(EntityName, + query, limit, offset).Result.Collection; + } + + [Obsolete("Use BrowseAsync() method.")] + public static ReleaseGroupList Browse(string relatedEntity, string value, int limit = 25, int offset = 0, params string[] inc) + { + return BrowseAsync(EntityName, + relatedEntity, value, limit, offset, inc).Result.Collection; + } + + /// + /// Lookup a release-group in the MusicBrainz database. + /// + /// The release-group MusicBrainz id. + /// A list of entities to include (subqueries). + /// + public async static Task GetAsync(string id, params string[] inc) + { + return await GetAsync(EntityName, id, inc); + } + + /// + /// Search for a release-group in the MusicBrainz database, matching the given query. + /// + /// The query string. + /// The maximum number of release-groups to return (default = 25). + /// The offset to the release-groups list (enables paging, default = 0). + /// + public async static Task SearchAsync(string query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query, limit, offset)).Collection; + } + + /// + /// Search for a release-group in the MusicBrainz database, matching the given query. + /// + /// The query parameters. + /// The maximum number of release-groups to return (default = 25). + /// The offset to the release-groups list (enables paging, default = 0). + /// + public async static Task SearchAsync(QueryParameters query, int limit = 25, int offset = 0) + { + return (await SearchAsync(EntityName, + query.ToString(), limit, offset)).Collection; + } + + /// + /// Browse all the release-groups in the MusicBrainz database, which are directly linked to the + /// entity with given id. + /// + /// The name of the related entity. + /// The id of the related entity. + /// The maximum number of release-groups to return (default = 25). + /// The offset to the release-groups list (enables paging, default = 0). + /// A list of entities to include (subqueries). + /// + public async static Task BrowseAsync(string entity, string id, int limit = 25, int offset = 0, params string[] inc) + { + return (await BrowseAsync(EntityName, entity, id, + limit, offset, inc)).Collection; + } + + // TODO: add string parameter 'type' and 'status' to browse methods + // see http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2#Release_Type_and_Status + + #endregion + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Tag.cs b/src/Hqub.MusicBrainz.API/Entities/Tag.cs new file mode 100644 index 000000000..17a1ed7a1 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Tag.cs @@ -0,0 +1,20 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("tag", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Tag + { + /// + /// Gets or sets the count. + /// + [XmlAttribute("count")] + public int Count { get; set; } + + /// + /// Gets or sets the name. + /// + [XmlElement("name")] + public string Name { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Track.cs b/src/Hqub.MusicBrainz.API/Entities/Track.cs new file mode 100644 index 000000000..95b9f98a4 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Track.cs @@ -0,0 +1,35 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("track", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Track + { + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the position. + /// + [XmlElement("position")] + public int Position { get; set; } + + // is almost always same as , so leaving it + + /// + /// Gets or sets the length. + /// + [XmlElement("length")] + public int Length { get; set; } + + /// + /// Gets or sets the recording. + /// + [XmlElement("recording")] + public Recording Recording { get; set; } + + } +} diff --git a/src/Hqub.MusicBrainz.API/Entities/Work.cs b/src/Hqub.MusicBrainz.API/Entities/Work.cs new file mode 100644 index 000000000..ff5289943 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Entities/Work.cs @@ -0,0 +1,26 @@ +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API.Entities +{ + [XmlRoot("work", Namespace = "http://musicbrainz.org/ns/mmd-2.0#")] + public class Work + { + /// + /// Gets or sets the MusicBrainz id. + /// + [XmlAttribute("id")] + public string Id { get; set; } + + /// + /// Gets or sets the title. + /// + [XmlElement("title")] + public string Title { get; set; } + + /// + /// Gets or sets the ISW code. + /// + [XmlElement("iswc")] + public string ISWC { get; set; } + } +} diff --git a/src/Hqub.MusicBrainz.API/Hqub.MusicBrainz.API.csproj b/src/Hqub.MusicBrainz.API/Hqub.MusicBrainz.API.csproj new file mode 100644 index 000000000..9c0a9b450 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Hqub.MusicBrainz.API.csproj @@ -0,0 +1,120 @@ + + + + + Debug + AnyCPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356} + Library + Properties + Hqub.MusicBrainz.API + Hqub.MusicBrainz.API + v4.5 + 512 + ..\ + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + bin\Travis\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Constants.resx + + + True + True + Messages.resx + + + + + + ResXFileCodeGenerator + Constants.Designer.cs + + + ResXFileCodeGenerator + Messages.Designer.cs + + + + + \ No newline at end of file diff --git a/src/Hqub.MusicBrainz.API/Properties/AssemblyInfo.cs b/src/Hqub.MusicBrainz.API/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b80eb5c01 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MusicBrainze.API")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Hqub.MusicBrainze.API")] +[assembly: AssemblyCopyright("Copyright h-qub © 2014-2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0b145d11-b090-4fe6-9294-5a73d67571a5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.1")] +[assembly: AssemblyFileVersion("1.0.1")] + +[assembly: InternalsVisibleTo("Hqub.MusicBrainz.API.Test")] diff --git a/src/Hqub.MusicBrainz.API/QueryParameters.cs b/src/Hqub.MusicBrainz.API/QueryParameters.cs new file mode 100644 index 000000000..9a5d40ee0 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/QueryParameters.cs @@ -0,0 +1,148 @@ +using Hqub.MusicBrainz.API.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Hqub.MusicBrainz.API +{ + /// + /// Helper for building MusicBrainz query strings. + /// + /// The entity type to search for. + /// + /// See https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search + /// + public class QueryParameters + where T : Entity + { + List values; + + public QueryParameters() + { + values = new List(); + } + + /// + /// Add a field to the query paramaters. + /// + /// The field key. + /// The field value. + /// Negate the field (will result in 'AND NOT key:value') + public void Add(string key, string value, bool negate = false) + { + if (string.IsNullOrEmpty(key)) + { + throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "key")); + } + + if (!Validate(key)) + { + throw new Exception(string.Format(Resources.Messages.InvalidQueryParameter, key)); + } + + values.Add(new QueryNode(key, value, negate)); + } + + public override string ToString() + { + return BuildQueryString(); + } + + private string BuildQueryString() + { + var sb = new StringBuilder(); + + string value; + + foreach (var item in values) + { + // Append operator. + if (sb.Length > 0) + { + sb.Append(" AND "); + } + + // Negate operator. + if (item.Negate) + { + sb.Append("NOT "); + } + + // Append key. + sb.Append(item.Key); + sb.Append(':'); + + // Append value. + value = item.Value; + + if (value.Contains("AND") || value.Contains("OR")) + { + if (!value.StartsWith("(")) + { + // The search value appears to be an expression, so enclose it in brackets. + sb.Append("(" + value + ")"); + } + else + { + sb.Append(value); + } + } + else if (value.Contains(" ") && !value.StartsWith("\"")) + { + // The search value contains whitespace but isn't quoted. + sb.Append("\"" + value + "\""); + } + else + { + // The search value is already quoted or doesn't need quoting, so just append it. + sb.AppendFormat(value); + } + } + + return sb.ToString(); + } + + private bool Validate(string key) + { + key = "-" + key + "-"; + + if (typeof(T) == typeof(Artist)) + { + return Resources.Constants.ArtistQueryParams.IndexOf(key) >= 0; + } + + if (typeof(T) == typeof(Recording)) + { + return Resources.Constants.RecordingQueryParams.IndexOf(key) >= 0; + } + + if (typeof(T) == typeof(Release)) + { + return Resources.Constants.ReleaseQueryParams.IndexOf(key) >= 0; + } + + if (typeof(T) == typeof(ReleaseGroup)) + { + return Resources.Constants.ReleaseGroupQueryParams.IndexOf(key) >= 0; + } + + return false; + } + + class QueryNode + { + public string Key { get; private set; } + public string Value { get; private set; } + public bool Negate { get; private set; } + + public QueryNode(string key, string value, bool negate) + { + this.Key = key; + this.Value = value; + this.Negate = negate; + } + } + } +} diff --git a/src/Hqub.MusicBrainz.API/Resources/Constants.Designer.cs b/src/Hqub.MusicBrainz.API/Resources/Constants.Designer.cs new file mode 100644 index 000000000..680f291fe --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Resources/Constants.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Hqub.MusicBrainz.API.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Constants { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Constants() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hqub.MusicBrainz.API.Resources.Constants", typeof(Constants).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to -area-beginarea-endarea-arid-artist-artistaccent-alias-begin-comment-country-end-ended-gender-ipi-sortname-tag-type-. + /// + internal static string ArtistQueryParams { + get { + return ResourceManager.GetString("ArtistQueryParams", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -arid-artist-artistname-creditname-comment-country-date-dur-format-isrc-number-position-primarytype-puid-qdur-recording-recordingaccent-reid-release-rgid--rid-secondarytype-status-tid-tnum-tracks-tracksrelease-tag-type-video-. + /// + internal static string RecordingQueryParams { + get { + return ResourceManager.GetString("RecordingQueryParams", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -arid-artist-artistname-comment-creditname-primarytype-rgid-releasegroup-releasegroupaccent-releases-release-reid-secondarytype-status-tag-type-. + /// + internal static string ReleaseGroupQueryParams { + get { + return ResourceManager.GetString("ReleaseGroupQueryParams", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -arid-artist-artistname-asin-barcode-catno-comment-country-creditname-date-discids-discidsmedium-format-laid-label-lang-mediums-primarytype-puid-quality-reid-release-releaseaccent-rgid-script-secondarytype-status-tag-tracks-tracksmedium-type-. + /// + internal static string ReleaseQueryParams { + get { + return ResourceManager.GetString("ReleaseQueryParams", resourceCulture); + } + } + } +} diff --git a/src/Hqub.MusicBrainz.API/Resources/Constants.resx b/src/Hqub.MusicBrainz.API/Resources/Constants.resx new file mode 100644 index 000000000..7a0a955ea --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Resources/Constants.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + -area-beginarea-endarea-arid-artist-artistaccent-alias-begin-comment-country-end-ended-gender-ipi-sortname-tag-type- + + + -arid-artist-artistname-creditname-comment-country-date-dur-format-isrc-number-position-primarytype-puid-qdur-recording-recordingaccent-reid-release-rgid--rid-secondarytype-status-tid-tnum-tracks-tracksrelease-tag-type-video- + + + -arid-artist-artistname-comment-creditname-primarytype-rgid-releasegroup-releasegroupaccent-releases-release-reid-secondarytype-status-tag-type- + + + -arid-artist-artistname-asin-barcode-catno-comment-country-creditname-date-discids-discidsmedium-format-laid-label-lang-mediums-primarytype-puid-quality-reid-release-releaseaccent-rgid-script-secondarytype-status-tag-tracks-tracksmedium-type- + + \ No newline at end of file diff --git a/src/Hqub.MusicBrainz.API/Resources/Messages.Designer.cs b/src/Hqub.MusicBrainz.API/Resources/Messages.Designer.cs new file mode 100644 index 000000000..d88ebdd52 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Resources/Messages.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Hqub.MusicBrainz.API.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Messages { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Messages() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hqub.MusicBrainz.API.Resources.Messages", typeof(Messages).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Query returned an empty result.. + /// + internal static string EmptyStream { + get { + return ResourceManager.GetString("EmptyStream", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Key not supported ({0}).. + /// + internal static string InvalidQueryParameter { + get { + return ResourceManager.GetString("InvalidQueryParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attribute '{0}' must be specified.. + /// + internal static string MissingParameter { + get { + return ResourceManager.GetString("MissingParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Webservice returned invalid response format.. + /// + internal static string WrongResponseFormat { + get { + return ResourceManager.GetString("WrongResponseFormat", resourceCulture); + } + } + } +} diff --git a/src/Hqub.MusicBrainz.API/Resources/Messages.resx b/src/Hqub.MusicBrainz.API/Resources/Messages.resx new file mode 100644 index 000000000..2d12b7538 --- /dev/null +++ b/src/Hqub.MusicBrainz.API/Resources/Messages.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Query returned an empty result. + + + Key not supported ({0}). + + + Attribute '{0}' must be specified. + + + Webservice returned invalid response format. + + \ No newline at end of file diff --git a/src/Hqub.MusicBrainz.API/WebRequestHelper.cs b/src/Hqub.MusicBrainz.API/WebRequestHelper.cs new file mode 100644 index 000000000..3f3b188dd --- /dev/null +++ b/src/Hqub.MusicBrainz.API/WebRequestHelper.cs @@ -0,0 +1,116 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using System.Xml.Linq; +using System.Xml.Serialization; + +namespace Hqub.MusicBrainz.API +{ + internal static class WebRequestHelper + { + private const string WebServiceUrl = "http://musicbrainz.org/ws/2/"; + private const string LookupTemplate = "{0}/{1}/?inc={2}"; + private const string BrowseTemplate = "{0}?{1}={2}&limit={3}&offset={4}&inc={5}"; + private const string SearchTemplate = "{0}?query={1}&limit={2}&offset={3}"; + + internal async static Task GetAsync(string url, bool withoutMetadata = true) where T : Entities.Entity + { + try + { + var client = CreateHttpClient(true, Configuration.Proxy); + + return DeserializeStream(await client.GetStreamAsync(url), withoutMetadata); + } + catch (Exception e) + { + if (Configuration.GenerateCommunicationThrow) + { + throw e; + } + } + + return default(T); + } + + /// + /// Creates a webservice lookup template. + /// + internal static string CreateLookupUrl(string entity, string mbid, string inc) + { + return string.Format("{0}{1}", WebServiceUrl, string.Format(LookupTemplate, entity, mbid, inc)); + } + + /// + /// Creates a webservice browse template. + /// + internal static string CreateBrowseTemplate(string entity, string relatedEntity, string mbid, int limit, int offset, string inc) + { + return string.Format("{0}{1}", WebServiceUrl, string.Format(BrowseTemplate, entity, relatedEntity, mbid, limit, offset, inc)); + } + + /// + /// Creates a webservice search template. + /// + internal static string CreateSearchTemplate(string entity, string query, int limit, int offset) + { + query = Uri.EscapeUriString(query); + + return string.Format("{0}{1}", WebServiceUrl, string.Format(SearchTemplate, entity, query, limit, offset)); + } + + internal static T DeserializeStream(Stream stream, bool withoutMetadata) where T : Entities.Entity + { + if (stream == null) + { + throw new NullReferenceException(Resources.Messages.EmptyStream); + } + + var xml = XDocument.Load(stream); + var serialize = new XmlSerializer(typeof(T)); + + //Add extension namespace: + var ns = new XmlSerializerNamespaces(); + ns.Add("ext", "http://musicbrainz.org/ns/ext#-2.0"); + + //check valid xml schema: + if (xml.Root == null || xml.Root.Name.LocalName != "metadata") + { + throw new NullReferenceException(Resources.Messages.WrongResponseFormat); + } + + var node = withoutMetadata ? xml.Root.Elements().FirstOrDefault() : xml.Root; + + if (node == null) + { + return default(T); + } + + return (T)serialize.Deserialize(node.CreateReader()); + } + + private static HttpClient CreateHttpClient(bool automaticDecompression = true, IWebProxy proxy = null) + { + var handler = new HttpClientHandler(); + + if (proxy != null) + { + handler.Proxy = proxy; + handler.UseProxy = true; + } + + if (automaticDecompression) + { + handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + + var client = new HttpClient(handler); + + client.DefaultRequestHeaders.Add("User-Agent", Configuration.UserAgent); + + return client; + } + } +} diff --git a/src/NzbDrone.sln b/src/NzbDrone.sln index 1acdb9d16..6c5141beb 100644 --- a/src/NzbDrone.sln +++ b/src/NzbDrone.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{57A04B72-8088-4F75-A582-1158CF8291F7}" EndProject @@ -90,192 +90,477 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogentriesNLog", "Logentrie EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CurlSharp", "ExternalModules\CurlSharp\CurlSharp\CurlSharp.csproj", "{74420A79-CC16-442C-8B1E-7C1B913844F0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hqub.MusicBrainz.API", "Hqub.MusicBrainz.API\Hqub.MusicBrainz.API.csproj", "{77832DED-EEFE-4DB9-94AF-B0BE02CEC356}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 + Mono|Any CPU = Mono|Any CPU Mono|x86 = Mono|x86 + Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 + Travis|Any CPU = Travis|Any CPU + Travis|x86 = Travis|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Any CPU.ActiveCfg = Debug|x86 {FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|x86.ActiveCfg = Debug|x86 {FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|x86.Build.0 = Debug|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Mono|Any CPU.ActiveCfg = Release|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Mono|Any CPU.Build.0 = Release|x86 {FAFB5948-A222-4CF6-AD14-026BE7564802}.Mono|x86.ActiveCfg = Release|x86 {FAFB5948-A222-4CF6-AD14-026BE7564802}.Mono|x86.Build.0 = Release|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|Any CPU.ActiveCfg = Release|x86 {FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x86.ActiveCfg = Release|x86 {FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x86.Build.0 = Release|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Travis|Any CPU.ActiveCfg = Release|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Travis|Any CPU.Build.0 = Release|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Travis|x86.ActiveCfg = Release|x86 + {FAFB5948-A222-4CF6-AD14-026BE7564802}.Travis|x86.Build.0 = Release|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Debug|Any CPU.ActiveCfg = Debug|x86 {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Debug|x86.ActiveCfg = Debug|x86 {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Debug|x86.Build.0 = Debug|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Mono|Any CPU.ActiveCfg = Release|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Mono|Any CPU.Build.0 = Release|x86 {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Mono|x86.ActiveCfg = Debug|x86 {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Mono|x86.Build.0 = Debug|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Release|Any CPU.ActiveCfg = Release|x86 {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Release|x86.ActiveCfg = Release|x86 {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Release|x86.Build.0 = Release|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Travis|Any CPU.ActiveCfg = Release|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Travis|Any CPU.Build.0 = Release|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Travis|x86.ActiveCfg = Release|x86 + {CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Travis|x86.Build.0 = Release|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Debug|Any CPU.ActiveCfg = Debug|x86 {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Debug|x86.ActiveCfg = Debug|x86 {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Debug|x86.Build.0 = Debug|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Mono|Any CPU.ActiveCfg = Release|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Mono|Any CPU.Build.0 = Release|x86 {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Mono|x86.ActiveCfg = Debug|x86 {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Mono|x86.Build.0 = Debug|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Release|Any CPU.ActiveCfg = Release|x86 {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Release|x86.ActiveCfg = Release|x86 {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Release|x86.Build.0 = Release|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Travis|Any CPU.ActiveCfg = Release|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Travis|Any CPU.Build.0 = Release|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Travis|x86.ActiveCfg = Release|x86 + {193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Travis|x86.Build.0 = Release|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Debug|Any CPU.ActiveCfg = Debug|x86 {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Debug|x86.ActiveCfg = Debug|x86 {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Debug|x86.Build.0 = Debug|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Mono|Any CPU.ActiveCfg = Release|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Mono|Any CPU.Build.0 = Release|x86 {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Mono|x86.ActiveCfg = Debug|x86 {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Mono|x86.Build.0 = Debug|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|Any CPU.ActiveCfg = Release|x86 {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x86.ActiveCfg = Release|x86 {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x86.Build.0 = Release|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Travis|Any CPU.ActiveCfg = Release|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Travis|Any CPU.Build.0 = Release|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Travis|x86.ActiveCfg = Release|x86 + {C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Travis|x86.Build.0 = Release|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Any CPU.ActiveCfg = Debug|x86 {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|x86.ActiveCfg = Debug|x86 {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|x86.Build.0 = Debug|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Mono|Any CPU.ActiveCfg = Release|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Mono|Any CPU.Build.0 = Release|x86 {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Mono|x86.ActiveCfg = Debug|x86 {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Mono|x86.Build.0 = Debug|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|Any CPU.ActiveCfg = Release|x86 {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x86.ActiveCfg = Release|x86 {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x86.Build.0 = Release|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Travis|Any CPU.ActiveCfg = Release|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Travis|Any CPU.Build.0 = Release|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Travis|x86.ActiveCfg = Release|x86 + {35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Travis|x86.Build.0 = Release|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Debug|Any CPU.ActiveCfg = Debug|x86 {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Debug|x86.ActiveCfg = Debug|x86 {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Debug|x86.Build.0 = Debug|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Mono|Any CPU.ActiveCfg = Release|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Mono|Any CPU.Build.0 = Release|x86 {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Mono|x86.ActiveCfg = Debug|x86 {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Mono|x86.Build.0 = Debug|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Release|Any CPU.ActiveCfg = Release|x86 {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Release|x86.ActiveCfg = Release|x86 {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Release|x86.Build.0 = Release|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Travis|Any CPU.ActiveCfg = Release|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Travis|Any CPU.Build.0 = Release|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Travis|x86.ActiveCfg = Release|x86 + {BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Travis|x86.Build.0 = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Debug|Any CPU.ActiveCfg = Debug|x86 {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Debug|x86.ActiveCfg = Debug|x86 {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Debug|x86.Build.0 = Debug|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Mono|Any CPU.ActiveCfg = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Mono|Any CPU.Build.0 = Release|x86 {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Mono|x86.ActiveCfg = Release|x86 {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Mono|x86.Build.0 = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Release|Any CPU.ActiveCfg = Release|x86 {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Release|x86.ActiveCfg = Release|x86 {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Release|x86.Build.0 = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Travis|Any CPU.ActiveCfg = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Travis|Any CPU.Build.0 = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Travis|x86.ActiveCfg = Release|x86 + {D18A5DEB-5102-4775-A1AF-B75DAAA8907B}.Travis|x86.Build.0 = Release|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Debug|Any CPU.ActiveCfg = Debug|x86 {CBF6B8B0-A015-413A-8C86-01238BB45770}.Debug|x86.ActiveCfg = Debug|x86 {CBF6B8B0-A015-413A-8C86-01238BB45770}.Debug|x86.Build.0 = Debug|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Mono|Any CPU.ActiveCfg = Release|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Mono|Any CPU.Build.0 = Release|x86 {CBF6B8B0-A015-413A-8C86-01238BB45770}.Mono|x86.ActiveCfg = Debug|x86 {CBF6B8B0-A015-413A-8C86-01238BB45770}.Mono|x86.Build.0 = Debug|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Release|Any CPU.ActiveCfg = Release|x86 {CBF6B8B0-A015-413A-8C86-01238BB45770}.Release|x86.ActiveCfg = Release|x86 {CBF6B8B0-A015-413A-8C86-01238BB45770}.Release|x86.Build.0 = Release|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Travis|Any CPU.ActiveCfg = Release|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Travis|Any CPU.Build.0 = Release|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Travis|x86.ActiveCfg = Release|x86 + {CBF6B8B0-A015-413A-8C86-01238BB45770}.Travis|x86.Build.0 = Release|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Debug|Any CPU.ActiveCfg = Debug|x86 {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Debug|x86.ActiveCfg = Debug|x86 {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Debug|x86.Build.0 = Debug|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Mono|Any CPU.ActiveCfg = Release|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Mono|Any CPU.Build.0 = Release|x86 {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Mono|x86.ActiveCfg = Debug|x86 {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Mono|x86.Build.0 = Debug|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Release|Any CPU.ActiveCfg = Release|x86 {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Release|x86.ActiveCfg = Release|x86 {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Release|x86.Build.0 = Release|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Travis|Any CPU.ActiveCfg = Release|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Travis|Any CPU.Build.0 = Release|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Travis|x86.ActiveCfg = Release|x86 + {8CEFECD0-A6C2-498F-98B1-3FBE5820F9AB}.Travis|x86.Build.0 = Release|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Debug|Any CPU.ActiveCfg = Debug|x86 {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Debug|x86.ActiveCfg = Debug|x86 {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Debug|x86.Build.0 = Debug|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Mono|Any CPU.ActiveCfg = Release|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Mono|Any CPU.Build.0 = Release|x86 {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Mono|x86.ActiveCfg = Debug|x86 {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Mono|x86.Build.0 = Debug|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Release|Any CPU.ActiveCfg = Release|x86 {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Release|x86.ActiveCfg = Release|x86 {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Release|x86.Build.0 = Release|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Travis|Any CPU.ActiveCfg = Release|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Travis|Any CPU.Build.0 = Release|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Travis|x86.ActiveCfg = Release|x86 + {CC26800D-F67E-464B-88DE-8EB1A0C227A3}.Travis|x86.Build.0 = Release|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Debug|Any CPU.ActiveCfg = Debug|x86 {6BCE712F-846D-4846-9D1B-A66B858DA755}.Debug|x86.ActiveCfg = Debug|x86 {6BCE712F-846D-4846-9D1B-A66B858DA755}.Debug|x86.Build.0 = Debug|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Mono|Any CPU.ActiveCfg = Release|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Mono|Any CPU.Build.0 = Release|x86 {6BCE712F-846D-4846-9D1B-A66B858DA755}.Mono|x86.ActiveCfg = Debug|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Release|Any CPU.ActiveCfg = Release|x86 {6BCE712F-846D-4846-9D1B-A66B858DA755}.Release|x86.ActiveCfg = Release|x86 {6BCE712F-846D-4846-9D1B-A66B858DA755}.Release|x86.Build.0 = Release|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Travis|Any CPU.ActiveCfg = Release|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Travis|Any CPU.Build.0 = Release|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Travis|x86.ActiveCfg = Release|x86 + {6BCE712F-846D-4846-9D1B-A66B858DA755}.Travis|x86.Build.0 = Release|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Debug|Any CPU.ActiveCfg = Debug|x86 {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Debug|x86.ActiveCfg = Debug|x86 {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Debug|x86.Build.0 = Debug|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Mono|Any CPU.ActiveCfg = Release|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Mono|Any CPU.Build.0 = Release|x86 {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Mono|x86.ActiveCfg = Debug|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Release|Any CPU.ActiveCfg = Release|x86 {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Release|x86.ActiveCfg = Release|x86 {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Release|x86.Build.0 = Release|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Travis|Any CPU.ActiveCfg = Release|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Travis|Any CPU.Build.0 = Release|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Travis|x86.ActiveCfg = Release|x86 + {700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Travis|x86.Build.0 = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Debug|Any CPU.ActiveCfg = Debug|x86 {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Debug|x86.ActiveCfg = Debug|x86 {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Debug|x86.Build.0 = Debug|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Mono|Any CPU.ActiveCfg = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Mono|Any CPU.Build.0 = Release|x86 {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Mono|x86.ActiveCfg = Release|x86 {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Mono|x86.Build.0 = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Release|Any CPU.ActiveCfg = Release|x86 {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Release|x86.ActiveCfg = Release|x86 {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Release|x86.Build.0 = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Travis|Any CPU.ActiveCfg = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Travis|Any CPU.Build.0 = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Travis|x86.ActiveCfg = Release|x86 + {FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Travis|x86.Build.0 = Release|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Any CPU.ActiveCfg = Debug|x86 {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|x86.ActiveCfg = Debug|x86 {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|x86.Build.0 = Debug|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Mono|Any CPU.ActiveCfg = Release|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Mono|Any CPU.Build.0 = Release|x86 {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Mono|x86.ActiveCfg = Debug|x86 {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Mono|x86.Build.0 = Debug|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|Any CPU.ActiveCfg = Release|x86 {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x86.ActiveCfg = Release|x86 {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x86.Build.0 = Release|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Travis|Any CPU.ActiveCfg = Release|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Travis|Any CPU.Build.0 = Release|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Travis|x86.ActiveCfg = Release|x86 + {4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Travis|x86.Build.0 = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Any CPU.ActiveCfg = Debug|x86 {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|x86.ActiveCfg = Debug|x86 {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|x86.Build.0 = Debug|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Mono|Any CPU.ActiveCfg = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Mono|Any CPU.Build.0 = Release|x86 {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Mono|x86.ActiveCfg = Release|x86 {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Mono|x86.Build.0 = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|Any CPU.ActiveCfg = Release|x86 {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|x86.ActiveCfg = Release|x86 {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|x86.Build.0 = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Travis|Any CPU.ActiveCfg = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Travis|Any CPU.Build.0 = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Travis|x86.ActiveCfg = Release|x86 + {F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Travis|x86.Build.0 = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Debug|Any CPU.ActiveCfg = Debug|x86 {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Debug|x86.ActiveCfg = Debug|x86 {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Debug|x86.Build.0 = Debug|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Mono|Any CPU.ActiveCfg = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Mono|Any CPU.Build.0 = Release|x86 {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Mono|x86.ActiveCfg = Release|x86 {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Mono|x86.Build.0 = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Release|Any CPU.ActiveCfg = Release|x86 {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Release|x86.ActiveCfg = Release|x86 {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Release|x86.Build.0 = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Travis|Any CPU.ActiveCfg = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Travis|Any CPU.Build.0 = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Travis|x86.ActiveCfg = Release|x86 + {FD286DF8-2D3A-4394-8AD5-443FADE55FB2}.Travis|x86.Build.0 = Release|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Debug|Any CPU.ActiveCfg = Debug|x86 {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Debug|x86.ActiveCfg = Debug|x86 {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Debug|x86.Build.0 = Debug|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Mono|Any CPU.ActiveCfg = Release|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Mono|Any CPU.Build.0 = Release|x86 {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Mono|x86.ActiveCfg = Debug|x86 {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Mono|x86.Build.0 = Debug|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Release|Any CPU.ActiveCfg = Release|x86 {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Release|x86.ActiveCfg = Release|x86 {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Release|x86.Build.0 = Release|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Travis|Any CPU.ActiveCfg = Release|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Travis|Any CPU.Build.0 = Release|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Travis|x86.ActiveCfg = Release|x86 + {3DCA7B58-B8B3-49AC-9D9E-56F4A0460976}.Travis|x86.Build.0 = Release|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Debug|Any CPU.ActiveCfg = Debug|x86 {95C11A9E-56ED-456A-8447-2C89C1139266}.Debug|x86.ActiveCfg = Debug|x86 {95C11A9E-56ED-456A-8447-2C89C1139266}.Debug|x86.Build.0 = Debug|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Mono|Any CPU.ActiveCfg = Release|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Mono|Any CPU.Build.0 = Release|x86 {95C11A9E-56ED-456A-8447-2C89C1139266}.Mono|x86.ActiveCfg = Debug|x86 {95C11A9E-56ED-456A-8447-2C89C1139266}.Mono|x86.Build.0 = Debug|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Release|Any CPU.ActiveCfg = Release|x86 {95C11A9E-56ED-456A-8447-2C89C1139266}.Release|x86.ActiveCfg = Release|x86 {95C11A9E-56ED-456A-8447-2C89C1139266}.Release|x86.Build.0 = Release|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Travis|Any CPU.ActiveCfg = Release|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Travis|Any CPU.Build.0 = Release|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Travis|x86.ActiveCfg = Release|x86 + {95C11A9E-56ED-456A-8447-2C89C1139266}.Travis|x86.Build.0 = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Debug|Any CPU.ActiveCfg = Debug|x86 {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Debug|x86.ActiveCfg = Debug|x86 {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Debug|x86.Build.0 = Debug|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Mono|Any CPU.ActiveCfg = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Mono|Any CPU.Build.0 = Release|x86 {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Mono|x86.ActiveCfg = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Release|Any CPU.ActiveCfg = Release|x86 {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Release|x86.ActiveCfg = Release|x86 {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Release|x86.Build.0 = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Travis|Any CPU.ActiveCfg = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Travis|Any CPU.Build.0 = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Travis|x86.ActiveCfg = Release|x86 + {D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Travis|x86.Build.0 = Release|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Debug|Any CPU.ActiveCfg = Debug|x86 {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Debug|x86.ActiveCfg = Debug|x86 {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Debug|x86.Build.0 = Debug|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Mono|Any CPU.ActiveCfg = Release|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Mono|Any CPU.Build.0 = Release|x86 {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Mono|x86.ActiveCfg = Debug|x86 {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Mono|x86.Build.0 = Debug|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Release|Any CPU.ActiveCfg = Release|x86 {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Release|x86.ActiveCfg = Release|x86 {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Release|x86.Build.0 = Release|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Travis|Any CPU.ActiveCfg = Release|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Travis|Any CPU.Build.0 = Release|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Travis|x86.ActiveCfg = Release|x86 + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}.Travis|x86.Build.0 = Release|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Debug|Any CPU.ActiveCfg = Debug|x86 {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Debug|x86.ActiveCfg = Debug|x86 {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Debug|x86.Build.0 = Debug|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Mono|Any CPU.ActiveCfg = Release|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Mono|Any CPU.Build.0 = Release|x86 {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Mono|x86.ActiveCfg = Debug|x86 {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Mono|x86.Build.0 = Debug|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Release|Any CPU.ActiveCfg = Release|x86 {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Release|x86.ActiveCfg = Release|x86 {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Release|x86.Build.0 = Release|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Travis|Any CPU.ActiveCfg = Release|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Travis|Any CPU.Build.0 = Release|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Travis|x86.ActiveCfg = Release|x86 + {1B9A82C4-BCA1-4834-A33E-226F17BE070B}.Travis|x86.Build.0 = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Debug|Any CPU.ActiveCfg = Debug|x86 {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Debug|x86.ActiveCfg = Debug|x86 {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Debug|x86.Build.0 = Debug|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Mono|Any CPU.ActiveCfg = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Mono|Any CPU.Build.0 = Release|x86 {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Mono|x86.ActiveCfg = Release|x86 {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Mono|x86.Build.0 = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Release|Any CPU.ActiveCfg = Release|x86 {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Release|x86.ActiveCfg = Release|x86 {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Release|x86.Build.0 = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Travis|Any CPU.ActiveCfg = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Travis|Any CPU.Build.0 = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Travis|x86.ActiveCfg = Release|x86 + {2B8C6DAD-4D85-41B1-83FD-248D9F347522}.Travis|x86.Build.0 = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Debug|Any CPU.ActiveCfg = Debug|x86 {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Debug|x86.ActiveCfg = Debug|x86 {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Debug|x86.Build.0 = Debug|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Mono|Any CPU.ActiveCfg = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Mono|Any CPU.Build.0 = Release|x86 {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Mono|x86.ActiveCfg = Release|x86 {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Mono|x86.Build.0 = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Release|Any CPU.ActiveCfg = Release|x86 {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Release|x86.ActiveCfg = Release|x86 {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Release|x86.Build.0 = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Travis|Any CPU.ActiveCfg = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Travis|Any CPU.Build.0 = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Travis|x86.ActiveCfg = Release|x86 + {F6FC6BE7-0847-4817-A1ED-223DC647C3D7}.Travis|x86.Build.0 = Release|x86 + {15AD7579-A314-4626-B556-663F51D97CD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15AD7579-A314-4626-B556-663F51D97CD1}.Debug|Any CPU.Build.0 = Debug|Any CPU {15AD7579-A314-4626-B556-663F51D97CD1}.Debug|x86.ActiveCfg = Debug|x86 {15AD7579-A314-4626-B556-663F51D97CD1}.Debug|x86.Build.0 = Debug|x86 + {15AD7579-A314-4626-B556-663F51D97CD1}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {15AD7579-A314-4626-B556-663F51D97CD1}.Mono|Any CPU.Build.0 = Release|Any CPU {15AD7579-A314-4626-B556-663F51D97CD1}.Mono|x86.ActiveCfg = Release|x86 + {15AD7579-A314-4626-B556-663F51D97CD1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15AD7579-A314-4626-B556-663F51D97CD1}.Release|Any CPU.Build.0 = Release|Any CPU {15AD7579-A314-4626-B556-663F51D97CD1}.Release|x86.ActiveCfg = Release|x86 {15AD7579-A314-4626-B556-663F51D97CD1}.Release|x86.Build.0 = Release|x86 + {15AD7579-A314-4626-B556-663F51D97CD1}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {15AD7579-A314-4626-B556-663F51D97CD1}.Travis|Any CPU.Build.0 = Release|Any CPU + {15AD7579-A314-4626-B556-663F51D97CD1}.Travis|x86.ActiveCfg = Release|x86 + {15AD7579-A314-4626-B556-663F51D97CD1}.Travis|x86.Build.0 = Release|x86 + {911284D3-F130-459E-836C-2430B6FBF21D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {911284D3-F130-459E-836C-2430B6FBF21D}.Debug|Any CPU.Build.0 = Debug|Any CPU {911284D3-F130-459E-836C-2430B6FBF21D}.Debug|x86.ActiveCfg = Debug|x86 {911284D3-F130-459E-836C-2430B6FBF21D}.Debug|x86.Build.0 = Debug|x86 + {911284D3-F130-459E-836C-2430B6FBF21D}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {911284D3-F130-459E-836C-2430B6FBF21D}.Mono|Any CPU.Build.0 = Release|Any CPU {911284D3-F130-459E-836C-2430B6FBF21D}.Mono|x86.ActiveCfg = Release|x86 + {911284D3-F130-459E-836C-2430B6FBF21D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {911284D3-F130-459E-836C-2430B6FBF21D}.Release|Any CPU.Build.0 = Release|Any CPU {911284D3-F130-459E-836C-2430B6FBF21D}.Release|x86.ActiveCfg = Release|x86 {911284D3-F130-459E-836C-2430B6FBF21D}.Release|x86.Build.0 = Release|x86 + {911284D3-F130-459E-836C-2430B6FBF21D}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {911284D3-F130-459E-836C-2430B6FBF21D}.Travis|Any CPU.Build.0 = Release|Any CPU + {911284D3-F130-459E-836C-2430B6FBF21D}.Travis|x86.ActiveCfg = Release|x86 + {911284D3-F130-459E-836C-2430B6FBF21D}.Travis|x86.Build.0 = Release|x86 + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Debug|Any CPU.Build.0 = Debug|Any CPU {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Debug|x86.ActiveCfg = Debug|x86 {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Debug|x86.Build.0 = Debug|x86 + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Mono|Any CPU.Build.0 = Release|Any CPU {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Mono|x86.ActiveCfg = Release|x86 + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Release|Any CPU.Build.0 = Release|Any CPU {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Release|x86.ActiveCfg = Release|x86 {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Release|x86.Build.0 = Release|x86 + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Travis|Any CPU.Build.0 = Release|Any CPU + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Travis|x86.ActiveCfg = Release|x86 + {80B51429-7A0E-46D6-BEE3-C80DCB1C4EAA}.Travis|x86.Build.0 = Release|x86 + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Debug|Any CPU.Build.0 = Debug|Any CPU {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Debug|x86.ActiveCfg = Debug|x86 {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Debug|x86.Build.0 = Debug|x86 + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Mono|Any CPU.Build.0 = Release|Any CPU {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Mono|x86.ActiveCfg = Release|x86 + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Release|Any CPU.Build.0 = Release|Any CPU {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Release|x86.ActiveCfg = Release|x86 {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Release|x86.Build.0 = Release|x86 + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Travis|Any CPU.Build.0 = Release|Any CPU + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Travis|x86.ActiveCfg = Release|x86 + {40D72824-7D02-4A77-9106-8FE0EEA2B997}.Travis|x86.Build.0 = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Debug|Any CPU.ActiveCfg = Debug|x86 {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Debug|x86.ActiveCfg = Debug|x86 {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Debug|x86.Build.0 = Debug|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Mono|Any CPU.ActiveCfg = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Mono|Any CPU.Build.0 = Release|x86 {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Mono|x86.ActiveCfg = Release|x86 {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Mono|x86.Build.0 = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Release|Any CPU.ActiveCfg = Release|x86 {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Release|x86.ActiveCfg = Release|x86 {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Release|x86.Build.0 = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Travis|Any CPU.ActiveCfg = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Travis|Any CPU.Build.0 = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Travis|x86.ActiveCfg = Release|x86 + {411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8}.Travis|x86.Build.0 = Release|x86 + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Debug|Any CPU.Build.0 = Debug|Any CPU {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Debug|x86.ActiveCfg = Debug|x86 {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Debug|x86.Build.0 = Debug|x86 + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Mono|Any CPU.Build.0 = Release|Any CPU {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Mono|x86.ActiveCfg = Release|x86 {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Mono|x86.Build.0 = Release|x86 + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Release|Any CPU.Build.0 = Release|Any CPU {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Release|x86.ActiveCfg = Release|x86 {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Release|x86.Build.0 = Release|x86 + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Travis|Any CPU.Build.0 = Release|Any CPU + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Travis|x86.ActiveCfg = Release|x86 + {90D6E9FC-7B88-4E1B-B018-8FA742274558}.Travis|x86.Build.0 = Release|x86 + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Debug|Any CPU.Build.0 = Debug|Any CPU {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Debug|x86.ActiveCfg = Debug|x86 {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Debug|x86.Build.0 = Debug|x86 + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Mono|Any CPU.Build.0 = Release|Any CPU {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Mono|x86.ActiveCfg = Release|x86 {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Mono|x86.Build.0 = Release|x86 + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Release|Any CPU.Build.0 = Release|Any CPU {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Release|x86.ActiveCfg = Release|x86 {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Release|x86.Build.0 = Release|x86 + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Travis|Any CPU.Build.0 = Release|Any CPU + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Travis|x86.ActiveCfg = Release|x86 + {9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Travis|x86.Build.0 = Release|x86 + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|Any CPU.Build.0 = Debug|Any CPU {74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|x86.ActiveCfg = Debug|Any CPU {74420A79-CC16-442C-8B1E-7C1B913844F0}.Debug|x86.Build.0 = Debug|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Mono|Any CPU.ActiveCfg = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Mono|Any CPU.Build.0 = Release|Any CPU {74420A79-CC16-442C-8B1E-7C1B913844F0}.Mono|x86.ActiveCfg = Release|Any CPU {74420A79-CC16-442C-8B1E-7C1B913844F0}.Mono|x86.Build.0 = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|Any CPU.Build.0 = Release|Any CPU {74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|x86.ActiveCfg = Release|Any CPU {74420A79-CC16-442C-8B1E-7C1B913844F0}.Release|x86.Build.0 = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Travis|Any CPU.ActiveCfg = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Travis|Any CPU.Build.0 = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Travis|x86.ActiveCfg = Release|Any CPU + {74420A79-CC16-442C-8B1E-7C1B913844F0}.Travis|x86.Build.0 = Release|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Debug|x86.ActiveCfg = Debug|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Debug|x86.Build.0 = Debug|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Mono|Any CPU.ActiveCfg = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Mono|Any CPU.Build.0 = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Mono|x86.ActiveCfg = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Mono|x86.Build.0 = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Release|Any CPU.Build.0 = Release|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Release|x86.ActiveCfg = Release|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Release|x86.Build.0 = Release|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Travis|Any CPU.ActiveCfg = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Travis|Any CPU.Build.0 = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Travis|x86.ActiveCfg = Travis|Any CPU + {77832DED-EEFE-4DB9-94AF-B0BE02CEC356}.Travis|x86.Build.0 = Travis|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE