private void LoadSettings()
    {
      using (Settings xmlreader = new MPSettings())
      {
        _defaultUser = xmlreader.GetValueAsString("audioscrobbler", "user", "");
        _decodeUtf8 = xmlreader.GetValueAsBool("audioscrobbler", "decodeutf8", false);
      }

      MusicDatabase mdb = MusicDatabase.Instance;
      _currentNeighbourMode = lastFMFeed.weeklyartistchart;

      _useDebugLog =
        (mdb.AddScrobbleUserSettings(Convert.ToString(mdb.AddScrobbleUser(_defaultUser)), "iDebugLog", -1) == 1)
          ? true
          : false;
      //int tmpRMode = mdb.AddScrobbleUserSettings(Convert.ToString(mdb.AddScrobbleUser(_defaultUser)), "iOfflineMode", -1);
      int tmpRand = mdb.AddScrobbleUserSettings(Convert.ToString(mdb.AddScrobbleUser(_defaultUser)), "iRandomness", -1);
      int tmpNMode = mdb.AddScrobbleUserSettings(Convert.ToString(mdb.AddScrobbleUser(_defaultUser)), "iNeighbourMode",
                                                 -1);

      switch (tmpNMode)
      {
        case 3:
          _currentNeighbourMode = lastFMFeed.topartists;
          break;
        case 1:
          _currentNeighbourMode = lastFMFeed.weeklyartistchart;
          break;
        case 0:
          _currentNeighbourMode = lastFMFeed.recenttracks;
          break;
        default:
          _currentNeighbourMode = lastFMFeed.weeklyartistchart;
          break;
      }

      _randomNessPercent = (tmpRand >= 25) ? tmpRand : 77;
      ArtistMatchPercent = 100 - (int)(0.9 * _randomNessPercent);
      _unwantedTags = buildTagBlacklist();
      LookupLock = new object();
    }
    public List<Song> getAudioScrobblerFeed(lastFMFeed feed_, string asUser_)
    {
      if (string.IsNullOrEmpty(asUser_))
      {
        asUser_ = _defaultUser;
      }

      switch (feed_)
      {
        case lastFMFeed.recenttracks:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "recenttracks.xml",
                             @"//recenttracks/track", feed_);
        case lastFMFeed.topartists:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "topartists.xml",
                             @"//topartists/artist", feed_);
        case lastFMFeed.weeklyartistchart:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "weeklyartistchart.xml",
                             @"//weeklyartistchart/artist", feed_);
        case lastFMFeed.toptracks:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "toptracks.xml",
                             @"//toptracks/track", feed_);
        case lastFMFeed.weeklytrackchart:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "weeklytrackchart.xml",
                             @"//weeklytrackchart/track", feed_);
        case lastFMFeed.neighbours:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "neighbours.xml",
                             @"//neighbours/user", feed_);
        case lastFMFeed.friends:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "friends.xml",
                             @"//friends/user", feed_);
        case lastFMFeed.toptags:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "tags.xml", @"//toptags/tag",
                             feed_);
        case lastFMFeed.chartstoptags:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/tag/toptags.xml", @"//toptags/tag", feed_);
        case lastFMFeed.systemrecs:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "systemrecs.xml",
                             @"//recommendations/artist", feed_);
        case lastFMFeed.profile:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "profile.xml", @"//profile",
                             feed_);
        case lastFMFeed.recentbannedtracks:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "recentbannedtracks.xml",
                             @"//recentbannedtracks/track", feed_);
        case lastFMFeed.recentlovedtracks:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "recentlovedtracks.xml",
                             @"//recentlovedtracks/track", feed_);
        default:
          return ParseXMLDoc(@"http://ws.audioscrobbler.com/1.0/user/" + asUser_ + "/" + "recenttracks.xml",
                             @"//recenttracks/track", feed_);
      }
    }
 public GeneralFeedRequest(lastFMFeed feedToSearch, string userForFeed)
   : base(RequestType.GetAudioScrobblerFeed)
 {
   FeedToSearch = feedToSearch;
   UserForFeed = userForFeed;
 }
 public GeneralFeedRequest(lastFMFeed feedToSearch, string userForFeed, GeneralFeedRequestHandler handler)
   : this(feedToSearch, userForFeed)
 {
   GeneralFeedRequestCompleted += handler;
 }
    private List<Song> ParseXMLDoc(string xmlFileInput, string queryNodePath, lastFMFeed xmlfeed)
    {
      List<Song> songList = new List<Song>(50);
      try
      {
        XmlDocument doc = new XmlDocument();

        string tmpFileName = DownloadTempFile(xmlFileInput);
        doc.Load(tmpFileName);
        XmlNodeList nodes = doc.SelectNodes(queryNodePath);

        foreach (XmlNode node in nodes)
        {
          Song nodeSong = new Song();
          foreach (XmlNode child in node.ChildNodes)
          {
            switch (xmlfeed)
            {
              case (lastFMFeed.recenttracks):
                if (child.Name == "artist" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Artist = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "name" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Title = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                else if (child.Name == "date" && child.ChildNodes.Count != 0)
                {
                  nodeSong.DateTimePlayed = Convert.ToDateTime(child.ChildNodes[0].Value);
                }
                break;
              case (lastFMFeed.recentbannedtracks):
                goto case lastFMFeed.recenttracks;
              case (lastFMFeed.recentlovedtracks):
                goto case lastFMFeed.recenttracks;
              case (lastFMFeed.topartists):
                if (child.Name == "name" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Artist = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                  //else if (child.Name == "name" && child.ChildNodes.Count != 0)
                  //  nodeSong.Title = ConvertUtf8StringToSystemCodepage(child.ChildNodes[0].Value);
                else if (child.Name == "playcount" && child.ChildNodes.Count != 0)
                {
                  try
                  {
                    nodeSong.TimesPlayed =
                      Convert.ToInt32(
                        Math.Round(Double.Parse(child.ChildNodes[0].Value, NumberStyles.Float,
                                                CultureInfo.InvariantCulture)));
                  }
                  catch (FormatException) {}
                  catch (OverflowException) {}
                }
                else if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                else if (child.Name == "match" && child.ChildNodes.Count != 0)
                {
                  nodeSong.LastFMMatch = child.ChildNodes[0].Value;
                }
                break;
              case (lastFMFeed.weeklyartistchart):
                goto case lastFMFeed.topartists;
              case (lastFMFeed.toptracks):
                if (child.Name == "artist" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Artist = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "name" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Title = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "playcount" && child.ChildNodes.Count != 0)
                {
                  try
                  {
                    nodeSong.TimesPlayed =
                      Convert.ToInt32(
                        Math.Round(Double.Parse(child.ChildNodes[0].Value, NumberStyles.Float,
                                                CultureInfo.InvariantCulture)));
                  }
                  catch (FormatException) {}
                  catch (OverflowException) {}
                }
                else if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                break;
              case (lastFMFeed.toptags):
                if (child.Name == "name" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Artist = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "count" && child.ChildNodes.Count != 0)
                {
                  try
                  {
                    nodeSong.TimesPlayed =
                      Convert.ToInt32(
                        Math.Round(Double.Parse(child.ChildNodes[0].Value, NumberStyles.Float,
                                                CultureInfo.InvariantCulture)));
                  }
                  catch (FormatException) {}
                  catch (OverflowException) {}
                }
                else if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                break;
                // doesn't work atm
              case (lastFMFeed.chartstoptags):
                if (!string.IsNullOrEmpty(node.Attributes["name"].Value))
                {
                  nodeSong.Artist = DecodeUtf8String(node.Attributes["name"].Value);
                }
                if (node.Attributes["count"].Value != "")
                {
                  try
                  {
                    nodeSong.TimesPlayed =
                      Convert.ToInt32(
                        Math.Round(Double.Parse(node.Attributes["count"].Value, NumberStyles.Float,
                                                CultureInfo.InvariantCulture)));
                  }
                  catch (FormatException) {}
                  catch (OverflowException) {}
                }
                if (node.Attributes["url"].Value != "")
                {
                  nodeSong.URL = node.Attributes["url"].Value;
                }
                break;
              case (lastFMFeed.neighbours):
                if (node.Attributes["username"].Value != "")
                {
                  nodeSong.Artist = node.Attributes["username"].Value;
                }
                if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                else if (child.Name == "match" && child.ChildNodes.Count != 0)
                {
                  nodeSong.LastFMMatch = child.ChildNodes[0].Value;
                }
                else if (child.Name == "image" && child.ChildNodes.Count != 0)
                {
                  nodeSong.WebImage = child.ChildNodes[0].Value;
                }
                break;
              case (lastFMFeed.friends):
                if (node.Attributes["username"].Value != "")
                {
                  nodeSong.Artist = node.Attributes["username"].Value;
                }
                if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                else if (child.Name == "image" && child.ChildNodes.Count != 0)
                {
                  nodeSong.WebImage = child.ChildNodes[0].Value;
                }
                //else if (child.Name == "connections" && child.ChildNodes.Count != 0)
                //  nodeSong.LastFMMatch = child.ChildNodes[0].Value;
                break;
              case (lastFMFeed.weeklytrackchart):
                goto case lastFMFeed.toptracks;
              case (lastFMFeed.similar):
                goto case lastFMFeed.topartists;
              case (lastFMFeed.systemrecs):
                if (child.Name == "name" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Artist = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                break;
              case (lastFMFeed.profile):
                if (node.Attributes["id"].Value != String.Empty)
                {
                  nodeSong.Id = Convert.ToInt32(node.Attributes["id"].Value);
                }
                if (node.Attributes["username"].Value != String.Empty)
                {
                  nodeSong.Artist = node.Attributes["username"].Value;
                }
                if (child.Name == "url" && child.ChildNodes.Count != 0)
                {
                  nodeSong.URL = child.ChildNodes[0].Value;
                }
                else if (child.Name == "realname" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Title = DecodeUtf8String(child.ChildNodes[0].Value);
                }
                else if (child.Name == "registered" && child.ChildNodes.Count != 0)
                {
                  try
                  {
                    nodeSong.TimesPlayed =
                      Convert.ToInt32(
                        Math.Round(Double.Parse(child.ChildNodes[0].Value, NumberStyles.Float,
                                                CultureInfo.InvariantCulture)));
                  }
                  catch (FormatException) {}
                  catch (OverflowException) {}
                }
                else if (child.Name == "statsreset" && child.ChildNodes.Count != 0)
                {
                  nodeSong.DateTimeModified = Convert.ToDateTime(child.ChildNodes[0].Value);
                }
                else if (child.Name == "country" && child.ChildNodes.Count != 0)
                {
                  nodeSong.Genre = child.ChildNodes[0].Value;
                }
                else if (child.Name == "playcount" && child.ChildNodes.Count != 0)
                {
                  nodeSong.TimesPlayed = Convert.ToInt32(child.ChildNodes[0].Value);
                }
                else if (child.Name == "avatar" && child.ChildNodes.Count != 0)
                {
                  nodeSong.WebImage = child.ChildNodes[0].Value;
                }
                break;
            } //switch
          }
          songList.Add(nodeSong);
        }
        File.Delete(tmpFileName);
      }
      catch
      {
        // input nice exception here...
      }
      return songList;
    }
    private List<Song> ParseXMLDocForTags(string taggedWith_, lastFMFeed searchType_)
    {
      List<Song> TagsList = new List<Song>(50);
      try
      {
        XmlDocument doc = new XmlDocument();
        XmlNodeList nodes;
        string tmpFileName;
        switch (searchType_)
        {
          case lastFMFeed.taggedartists:
            tmpFileName = DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/tag/" + taggedWith_ + "/topartists.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//tag/artist");
            break;
          case lastFMFeed.taggedalbums:
            tmpFileName = DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/tag/" + taggedWith_ + "/topalbums.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//tag/album");
            break;
          case lastFMFeed.taggedtracks:
            tmpFileName = DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/tag/" + taggedWith_ + "/toptracks.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//tag/track");
            break;
          default:
            tmpFileName = DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/tag/" + taggedWith_ + "/topartists.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//tag/artist");
            break;
        }

        foreach (XmlNode node in nodes)
        {
          Song nodeSong = new Song();
          foreach (XmlNode child in node.ChildNodes)
          {
            switch (searchType_)
            {
              case lastFMFeed.taggedartists:
                if (!string.IsNullOrEmpty(node.Attributes["name"].Value))
                {
                  nodeSong.Artist = DecodeUtf8String(node.Attributes["name"].Value);
                }
                if (child.Name == "image" && child.ChildNodes.Count != 0)
                {
                  nodeSong.WebImage = child.ChildNodes[0].Value;
                }
                break;
              case lastFMFeed.taggedalbums:
                if (!string.IsNullOrEmpty(node.Attributes["name"].Value))
                {
                  nodeSong.Album = DecodeUtf8String(node.Attributes["name"].Value);
                }
                if (child.Name == "artist" && child.ChildNodes.Count != 0)
                {
                  if (string.IsNullOrEmpty(child.Attributes["name"].Value))
                  {
                    nodeSong.Artist = DecodeUtf8String(child.Attributes["name"].Value);
                  }
                }
                break;
              case lastFMFeed.taggedtracks:
                if (!string.IsNullOrEmpty(node.Attributes["name"].Value))
                {
                  nodeSong.Title = DecodeUtf8String(node.Attributes["name"].Value);
                }
                if (child.Name == "artist" && child.ChildNodes.Count != 0)
                {
                  if (!string.IsNullOrEmpty(child.Attributes["name"].Value))
                  {
                    nodeSong.Artist = DecodeUtf8String(child.Attributes["name"].Value);
                  }
                }
                break;
            }
            if (child.Name == "url" && child.ChildNodes.Count != 0)
            {
              nodeSong.URL = child.ChildNodes[0].Value;
            }
            if (node.Attributes["count"].Value != "")
            {
              try
              {
                nodeSong.TimesPlayed =
                  Convert.ToInt32(
                    Math.Round(Double.Parse(node.Attributes["count"].Value, NumberStyles.Float,
                                            CultureInfo.InvariantCulture)));
              }
              catch (FormatException) {}
              catch (OverflowException) {}
            }
          }
          TagsList.Add(nodeSong);
        }

        File.Delete(tmpFileName);
      }
      catch
      {
        // input nice exception here...
      }
      return TagsList;
    }
    /// <summary>
    /// Parses an artist or track for its most used tags
    /// </summary>
    /// <param name="artist_">artist to search</param>
    /// <param name="track_">track to search</param>
    /// <param name="searchType_">topartisttags or toptracktags</param>
    /// <returns>List of Song with Genre, TimesPlayed and URL</returns>
    private List<Song> ParseXMLDocForUsedTags(string artist_, string track_, lastFMFeed searchType_)
    {
      List<Song> UsedTagsList = new List<Song>();
      try
      {
        XmlDocument doc = new XmlDocument();
        XmlNodeList nodes;
        string tmpFileName;
        switch (searchType_)
        {
          case lastFMFeed.topartisttags:
            tmpFileName = DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/artist/" + artist_ + "/toptags.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//toptags/tag");
            break;
          case lastFMFeed.toptracktags:
            tmpFileName =
              DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/track/" + artist_ + "/" + track_ + "/toptags.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//toptags/tag");
            break;

          default:
            tmpFileName = DownloadTempFile(@"http://ws.audioscrobbler.com/1.0/artist/" + artist_ + "/toptags.xml");
            doc.Load(tmpFileName);
            nodes = doc.SelectNodes(@"//toptags/tag");
            break;
        }

        foreach (XmlNode node in nodes)
        {
          Song nodeSong = new Song();
          foreach (XmlNode child in node.ChildNodes)
          {
            //if (doc.Attributes["artist"].Value != "")
            //  nodeSong.Artist = doc.Attributes["artist"].Value;
            //if (doc.Attributes["track"].Value != "")
            //  nodeSong.Title = doc.Attributes["track"].Value;
            nodeSong.Artist = artist_;
            nodeSong.Title = track_;
            if (child.Name == "name" && child.ChildNodes.Count != 0)
            {
              nodeSong.Genre = DecodeUtf8String(child.ChildNodes[0].Value);
            }
            if (child.Name == "url" && child.ChildNodes.Count != 0)
            {
              nodeSong.URL = child.ChildNodes[0].Value;
            }
            if (child.Name == "count" && child.ChildNodes.Count != 0)
            {
              try
              {
                nodeSong.TimesPlayed =
                  Convert.ToInt32(
                    Math.Round(Double.Parse(child.ChildNodes[0].Value, NumberStyles.Float, CultureInfo.InvariantCulture)));
              }
              catch (FormatException) {}
              catch (OverflowException) {}
            }
          }
          UsedTagsList.Add(nodeSong);
        }

        File.Delete(tmpFileName);
      }
      catch
      {
        // input nice exception here...
      }
      return UsedTagsList;
    }
    private List<Song> getOthersArtists(bool randomizeList_, lastFMFeed neighbourOrFriend_)
    {
      List<Song> myNeighbours = new List<Song>(50);
      List<Song> myRandomNeighbours = new List<Song>();
      List<Song> myNeighboorsArtists = new List<Song>(50);
      List<Song> myRandomNeighboorsArtists = new List<Song>();

      switch (neighbourOrFriend_)
      {
        case lastFMFeed.neighbours:
          myNeighbours = getAudioScrobblerFeed(lastFMFeed.neighbours, "");
          break;
        case lastFMFeed.friends:
          myNeighbours = getAudioScrobblerFeed(lastFMFeed.friends, "");
          break;
      }

      if (randomizeList_)
      {
        PseudoRandomNumberGenerator rand = new PseudoRandomNumberGenerator();
        int neighboursAdded = 0;
        int randomPosition;
        // make sure we do not get an endless loop
        if (myNeighbours.Count > _limitRandomListCount)
        {
          int minRandValue = _limitRandomListCount;
          int calcRandValue = (myNeighbours.Count - 1) * _randomNessPercent / 100;
          while (neighboursAdded < _limitRandomListCount)
          {
            bool foundDoubleEntry = false;
            if (calcRandValue > minRandValue)
            {
              randomPosition = rand.Next(0, calcRandValue);
            }
            else
            {
              randomPosition = rand.Next(0, minRandValue);
            }

            // loop current list to find out if randomPos was already inserted
            for (int j = 0; j < myRandomNeighbours.Count; j++)
            {
              if (myRandomNeighbours.Contains(myNeighbours[randomPosition]))
              {
                foundDoubleEntry = true;
                break;
              }
            }
            // new item therefore add it
            if (!foundDoubleEntry)
            {
              myRandomNeighbours.Add(myNeighbours[randomPosition]);
              neighboursAdded++;
            }
          }
          // now _limitRandomListCount random neighbours are added
          // get artists for these neighbours  
          for (int n = 0; n < myRandomNeighbours.Count; n++)
          {
            myNeighboorsArtists = getAudioScrobblerFeed(_currentNeighbourMode, myRandomNeighbours[n].Artist);

            if (myNeighboorsArtists.Count > 0)
            {
              if (myNeighboorsArtists[0].LastFMMatch != string.Empty)
              {
                myNeighboorsArtists.Sort(CompareSongsByMatch);
              }
              else if (myNeighboorsArtists[0].TimesPlayed >= 0)
              {
                myNeighboorsArtists.Sort(CompareSongsByTimesPlayed);
              }
            }
            // make sure the neighbour has enough top artists
            if (myNeighboorsArtists.Count > _limitRandomListCount)
            {
              // get _limitRandomListCount artists for each random neighbour
              int artistsAdded = 0;
              int artistsPerNeighbour = _limitRandomListCount / myNeighbours.Count;
              // make sure there is at least one song per neighbour
              artistsPerNeighbour = artistsPerNeighbour > 1 ? artistsPerNeighbour : 1;
              int minRandAValue = _limitRandomListCount;
              int calcRandAValue = (myNeighboorsArtists.Count - 1) * _randomNessPercent / 100;
              while (artistsAdded <= artistsPerNeighbour)
              {
                bool foundDoubleEntry = false;
                if (calcRandAValue > minRandAValue)
                {
                  randomPosition = rand.Next(0, calcRandAValue);
                }
                else
                {
                  randomPosition = rand.Next(0, minRandAValue);
                }

                for (int j = 0; j < myRandomNeighboorsArtists.Count; j++)
                {
                  if (myRandomNeighboorsArtists.Contains(myNeighboorsArtists[randomPosition]))
                  {
                    foundDoubleEntry = true;
                    break;
                  }
                }
                // new item therefore add it
                if (!foundDoubleEntry)
                {
                  myRandomNeighboorsArtists.Add(myNeighboorsArtists[randomPosition]);
                  artistsAdded++;
                }
              }
            }
          }
          return myRandomNeighboorsArtists;
        }
        else
          // limit not reached - return all neighbours random artists          
        {
          for (int i = 0; i < myNeighbours.Count; i++)
          {
            // sort by match needed
            myNeighboorsArtists = getAudioScrobblerFeed(_currentNeighbourMode, myNeighbours[i].Artist);
            if (myNeighboorsArtists.Count > 0)
            {
              if (myNeighboorsArtists[0].LastFMMatch != string.Empty)
              {
                myNeighboorsArtists.Sort(CompareSongsByMatch);
              }
              else if (myNeighboorsArtists[0].TimesPlayed >= 0)
              {
                myNeighboorsArtists.Sort(CompareSongsByTimesPlayed);
              }
            }

            // make sure the neighbour has enough top artists
            if (myNeighboorsArtists.Count > _limitRandomListCount)
            {
              // get _limitRandomListCount artists for each neighbour
              int artistsAdded = 0;
              int artistsPerNeighbour = _limitRandomListCount / myNeighbours.Count;
              // make sure there is at least one song per neighbour
              artistsPerNeighbour = artistsPerNeighbour > 1 ? artistsPerNeighbour : 1;
              int minRandAValue = _limitRandomListCount;
              int calcRandAValue = (myNeighboorsArtists.Count - 1) * _randomNessPercent / 100;
              while (artistsAdded <= artistsPerNeighbour)
              {
                bool foundDoubleEntry = false;
                if (calcRandAValue > minRandAValue)
                {
                  randomPosition = rand.Next(0, calcRandAValue);
                }
                else
                {
                  randomPosition = rand.Next(0, minRandAValue);
                }

                for (int j = 0; j < myNeighboorsArtists.Count; j++)
                {
                  if (myRandomNeighboorsArtists.Contains(myNeighboorsArtists[randomPosition]))
                  {
                    foundDoubleEntry = true;
                    break;
                  }
                }
                // new item therefore add it
                if (!foundDoubleEntry)
                {
                  myRandomNeighboorsArtists.Add(myNeighboorsArtists[randomPosition]);
                  artistsAdded++;
                }
              }
            }
          }
          return myRandomNeighboorsArtists;
        }
      }
        // do not randomize
      else
      {
        if (myNeighbours.Count > 4)
        {
          for (int i = 0; i < 4; i++)
          {
            myNeighboorsArtists.AddRange(getAudioScrobblerFeed(_currentNeighbourMode, myNeighbours[i].Artist));
          }
        }
        return myNeighboorsArtists;
      }
    }
    public List<Song> getSimilarToTag(lastFMFeed searchType_, string taggedWith_, bool randomizeList_,
                                      bool addAvailableTracksOnly_)
    {
      songFilterType currentFilterType = songFilterType.Track;
      switch (searchType_)
      {
        case lastFMFeed.taggedtracks:
          currentFilterType = songFilterType.Track;
          break;
        case lastFMFeed.taggedartists:
          currentFilterType = songFilterType.Artist;
          break;
        case lastFMFeed.taggedalbums:
          currentFilterType = songFilterType.Album;
          break;
      }

      if (randomizeList_)
      {
        PseudoRandomNumberGenerator rand = new PseudoRandomNumberGenerator();
        List<Song> taggedArtists = new List<Song>(50);
        List<Song> randomTaggedArtists = new List<Song>(_limitRandomListCount);

        int artistsAdded = 0;
        int randomPosition;
        int oldRandomLimit = 10;
        oldRandomLimit = _limitRandomListCount;
        _limitRandomListCount = 50;

        taggedArtists = ParseXMLDocForTags(taggedWith_, searchType_);

        // make sure we do not get an endless loop
        if (taggedArtists.Count > _limitRandomListCount)
        {
          int minRandValue = _limitRandomListCount;
          int calcRandValue = (taggedArtists.Count - 1) * _randomNessPercent / 100;
          while (artistsAdded < _limitRandomListCount)
          {
            bool foundDoubleEntry = false;
            if (calcRandValue > minRandValue)
            {
              randomPosition = rand.Next(0, calcRandValue);
            }
            else
            {
              randomPosition = rand.Next(0, minRandValue);
            }
            // loop current list to find out if randomPos was already inserted
            for (int j = 0; j < randomTaggedArtists.Count; j++)
            {
              if (randomTaggedArtists.Contains(taggedArtists[randomPosition]))
              {
                foundDoubleEntry = true;
                break;
              }
            }
            // new item therefore add it
            if (!foundDoubleEntry)
            {
              //taggedArtists[randomPosition].Genre = taggedWith_;
              randomTaggedArtists.Add(taggedArtists[randomPosition]);
              artistsAdded++;
            }
          }
          _limitRandomListCount = oldRandomLimit;
          // enough similar artists
          if (addAvailableTracksOnly_)
          {
            return filterForLocalSongs(randomTaggedArtists, true, currentFilterType);
          }
          else
          {
            return randomTaggedArtists;
          }
        }
        else
        {
          // limit not reached - return all Artists
          if (addAvailableTracksOnly_)
          {
            return filterForLocalSongs(taggedArtists, true, currentFilterType);
          }
          else
          {
            return taggedArtists;
          }
        }
      }
      else
      {
        if (addAvailableTracksOnly_)
        {
          return filterForLocalSongs(ParseXMLDocForTags(taggedWith_, searchType_), true, currentFilterType);
        }
        else
        {
          return ParseXMLDocForTags(taggedWith_, searchType_);
        }
      }
    }