private bool ScrobbleSimilarArtists(string Artist_)
    {
      MusicDatabase dbs = MusicDatabase.Instance;
      PlayList list = playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_MUSIC);
      List<Song> songList = new List<Song>();
      double avgPlayCount = 0;
      int songsAdded = 0;
      int j = 0;

      dbs.GetSongsByArtist(Artist_, ref songList);

      //      Log.Debug("GUIMusicPlaylist: ScrobbleSimilarArtists found {0} songs allowed to add", Convert.ToString(songList.Count));

      // exit if not enough songs were found
      if (songList.Count < _maxScrobbledSongsPerArtist)
      {
        return false;
      }

      // lookup how many times this artist's songs were played
      avgPlayCount = dbs.GetAveragePlayCountForArtist(Artist_);

      switch (_preferCountForTracks)
      {
        case 0:
          // delete all heard songs
          for (int s = 0; s < songList.Count; s++)
          {
            if (songList[s].TimesPlayed > 0)
            {
              songList.Remove(songList[s]);
              s--;
            }
          }
          break;
        case 1:
          // delete all well known songs
          if (avgPlayCount < 0.5)
          {
            goto case 0;
          }
          else
          {
            for (int s = 0; s < songList.Count; s++)
            {
              // song was played more often than average
              if (songList[s].TimesPlayed > avgPlayCount)
              {
                // give 1x played songs a chance...
                if (songList[s].TimesPlayed > 1)
                {
                  songList.Remove(songList[s]);
                }
              }
            }
          }
          break;
        case 2:
          break;
        case 3:
          // only well known songs
          for (int s = 0; s < songList.Count; s++)
          {
            // delete all rarely heard songs
            if (songList[s].TimesPlayed < avgPlayCount)
            {
              songList.Remove(songList[s]);
              s--;
            }
          }

          // get new average playcount of remaining files
          if (songList.Count > 0)
          {
            int avgOfKnownSongs = 0;
            foreach (Song favSong in songList)
            {
              avgOfKnownSongs += favSong.TimesPlayed;
            }
            avgOfKnownSongs /= songList.Count;
            avgOfKnownSongs = avgOfKnownSongs > 0 ? avgOfKnownSongs : 2;

            int songListCount = songList.Count;
            for (int s = 0; s < songListCount; s++)
            {
              if (songList[s].TimesPlayed < avgOfKnownSongs)
              {
                songList.Remove(songList[s]);
                songListCount = songList.Count;
                s--;
              }
            }
          }
          //songList.Sort(CompareSongsByTimesPlayed);
          break;
      }

      // check if there are still enough songs
      if (songList.Count < _maxScrobbledSongsPerArtist)
      {
        return false;
      }

      PseudoRandomNumberGenerator rand = new PseudoRandomNumberGenerator();

      int randomPosition;

      while (songsAdded < _maxScrobbledSongsPerArtist)
      {
        if (_preferCountForTracks == 3)
        {
          randomPosition = rand.Next(0, songList.Count / 2);
        }
        else
        {
          randomPosition = rand.Next(0, songList.Count - 1);
        }

        Song refSong = new Song();

        refSong = songList[randomPosition];

        //        Log.Debug("GUIMusicPlaylist: ScrobbleSimilarArtists tries to add this song - {0}", refSong.ToShortString());

        if (AddRandomSongToPlaylist(ref refSong))
        {
          songsAdded++;
          _totalScrobbledSongs++;
        }

        j++;

        if (j > songList.Count * 5)
        {
          break;
        }
      }
      // _maxScrobbledSongsPerArtist are inserted
      return true;
    }
    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> getSimilarArtists(string Artist_, bool randomizeList_)
 {
   Artist_ = AudioscrobblerBase.getValidURLLastFMString(AudioscrobblerBase.UndoArtistPrefix(Artist_));
   if (randomizeList_)
   {
     PseudoRandomNumberGenerator rand = new PseudoRandomNumberGenerator();
     List<Song> similarArtists = new List<Song>(50);
     List<Song> randomSimilarArtists = new List<Song>(_limitRandomListCount);
     similarArtists = ParseXMLDocForSimilarArtists(Artist_);
     int artistsAdded = 0;
     int randomPosition;
     // make sure we do not get an endless loop
     if (similarArtists.Count > _limitRandomListCount)
     {
       int minRandValue = _limitRandomListCount;
       int calcRandValue = (similarArtists.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 < randomSimilarArtists.Count; j++)
         {
           if (randomSimilarArtists.Contains(similarArtists[randomPosition]))
           {
             foundDoubleEntry = true;
             break;
           }
         }
         // new item therefore add it
         if (!foundDoubleEntry)
         {
           randomSimilarArtists.Add(similarArtists[randomPosition]);
           artistsAdded++;
         }
       }
       // enough similar artists
       return randomSimilarArtists;
     }
     else
     {
       // limit not reached - return all Artists
       return similarArtists;
     }
   }
   else
   {
     return ParseXMLDocForSimilarArtists(Artist_);
   }
 }
    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_);
        }
      }
    }
    /// <summary>
    /// fetch other Tracks from last.fm which correspond to the tags of the given Track
    /// </summary>
    /// <param name="artistToSearch_">Artist name (can be unparsed)</param>
    /// <param name="trackToSearch_">Track name (can be unparsed)</param>
    /// <param name="randomizeUsedTag_">chose randomly between the 5 top tags</param>
    /// <param name="sortBestTracks_">do not apply randomness on track lookup</param>
    /// <param name="addAvailableTracksOnly">filter all songs not locally available</param>
    /// <returns>List of Song where Song.Genre contains the used tag</returns>
    public List<Song> getTagInfo(string artistToSearch_, string trackToSearch_, bool randomizeUsedTag_,
                                 bool sortBestTracks_, bool addAvailableTracksOnly)
    {
      int randomPosition = 0;
      int calcRandValue = 0;
      PseudoRandomNumberGenerator rand = new PseudoRandomNumberGenerator();
      string urlArtist = AudioscrobblerBase.getValidURLLastFMString(AudioscrobblerBase.UndoArtistPrefix(artistToSearch_));
      string urlTrack = AudioscrobblerBase.getValidURLLastFMString(trackToSearch_);
      string tmpGenre = string.Empty;
      List<Song> tagTracks = new List<Song>();

      // fetch the most popular Tags for the current track
      tagTracks = getTagsForTrack(urlArtist, urlTrack);

      // no tags for current track - try artist tags instead
      if (tagTracks.Count < 1)
      {
        tagTracks = getTagsForArtist(urlArtist);
      }

      if (tagTracks.Count > 0)
      {
        if (randomizeUsedTag_)
        {
          // decide which tag to use            
          // only use the "better" 50% for randomness
          //calcRandValue = ((tagTracks.Count / 2) - 1) * _randomNessPercent / 100;

          // only use the top 10 tags
          if (tagTracks.Count > _limitRandomListCount)
          {
            calcRandValue = (_limitRandomListCount) * _randomNessPercent / 100;
          }
          else
          {
            calcRandValue = ((tagTracks.Count) - 1) * _randomNessPercent / 100;
          }

          // make sure calcRandValue is not lower then random(minvalue, )
          calcRandValue = calcRandValue > 0 ? calcRandValue : 0;

          randomPosition = rand.Next(0, calcRandValue);
        }

        if (randomPosition < tagTracks.Count - 1)
        {
          for (int x = 0; x < _limitRandomListCount; x++)
          {
            tmpGenre = tagTracks[randomPosition].Genre.ToLowerInvariant();
            // filter unwanted tags
            if (_unwantedTags.Contains(tmpGenre.ToLowerInvariant()))
            {
              randomPosition = rand.Next(0, calcRandValue);
              // Log.Debug("AudioScrobblerUtils: Tag {0} in blacklist, randomly chosing another one", tmpGenre);
              // do not try to often..
              // if random picking doesn't lead to a result quit the randomness and pick the best
              if (x > tagTracks.Count * 3)
              {
                for (int t = 0; t < tagTracks.Count; t++)
                {
                  tmpGenre = tagTracks[t].Genre.ToLowerInvariant();
                  if (!_unwantedTags.Contains(tmpGenre.ToLowerInvariant()))
                  {
                    Log.Debug("AudioScrobblerUtils: Tag {0} was the first non-blacklisted item", tmpGenre);
                    break;
                  }

                  if (t == tagTracks.Count - 1)
                  {
                    tmpGenre = tagTracks[0].Genre.ToLowerInvariant();
                    //Log.Debug("AudioScrobblerUtils: Random tag picking unsuccessful - selecting {0}", tmpGenre);
                    break;
                  }
                }
              }
            }
            else
            {
              Log.Debug("AudioScrobblerUtils: Tag picking successful - selecting {0}", tmpGenre);
              break;
            }
          }
        }
        else
        {
          //Log.Debug("AudioScrobblerUtils: randomPosition {0} not reasonable for list of {1} tags", randomPosition, tagTracks.Count);
          if (tagTracks.Count == 1)
          {
            tmpGenre = tagTracks[0].Genre.ToLowerInvariant();
            Log.Debug("AudioScrobblerUtils: Tag {0} is the only one found - selecting..", tmpGenre);
          }
        }

        if (tmpGenre != string.Empty)
        {
          // use the best matches for the given track only            
          if (sortBestTracks_)
          {
            tagTracks = getSimilarToTag(lastFMFeed.taggedtracks, tmpGenre, false, addAvailableTracksOnly);
          }
          else
          {
            tagTracks = getSimilarToTag(lastFMFeed.taggedtracks, tmpGenre, true, addAvailableTracksOnly);
          }

          //// filter tracks not available in music database
          //if (addAvailableTracksOnly)
          //{
          //  tagTracks = filterForLocalSongs(tagTracks, artistToSearch_, tmpGenre);
          //}
        }
        else
        {
          tagTracks.Clear();
        }
      }

      // sort list by playcount (times a track was tagged in this case)
      if (sortBestTracks_)
      {
        tagTracks.Sort(CompareSongsByTimesPlayed);
      }

      foreach (Song tagSong in tagTracks)
      {
        tagSong.Genre = tmpGenre;
      }

      return tagTracks;
    }
    public bool GetRandomSong(ref Song aSong)
    {
      try
      {
        aSong.Clear();

        PseudoRandomNumberGenerator rand = new PseudoRandomNumberGenerator();

        int maxIDSong, rndIDSong;
        string strSQL = String.Format("SELECT max(idTrack) FROM tracks");

        SQLiteResultSet results = DirectExecute(strSQL);

        maxIDSong = DatabaseUtility.GetAsInt(results, 0, 0);
        rndIDSong = rand.Next(0, maxIDSong);

        strSQL = String.Format("SELECT * FROM tracks WHERE idTrack={0}", rndIDSong);

        results = DirectExecute(strSQL);
        if (results.Rows.Count > 0)
        {
          if (AssignAllSongFieldsFromResultSet(ref aSong, results, 0))
          {
            return true;
          }
        }
        else
        {
          GetRandomSong(ref aSong);
          return true;
        }
      }
      catch (Exception ex)
      {
        Log.Error("musicdatabase exception err:{0} stack:{1}", ex.Message, ex.StackTrace);
        Open();
      }

      return false;
    }