Index: mythmusic/mythmusic/playlist.h
===================================================================
--- mythmusic/mythmusic/playlist.h	(révision 16138)
+++ mythmusic/mythmusic/playlist.h	(copie de travail)
@@ -135,7 +135,15 @@
     int CreateCDAudio(void);
 
   private:
-    QString             removeDuplicateTracks(const QString &new_songlist);
+    void    computeIntelliOrder(QPtrList<Track>&        songs,
+                                std::map<int,uint32_t>& order,
+                                int                     playcountMin,
+                                int                     playcountMax,
+                                double                  lastplayMin,
+                                double                  lastplayMax);
+    QString removeDuplicateTracks(const QString &new_songlist);
+
+  private:
     int                 playlistid;
     QString             name;
     QString             raw_songlist;
Index: mythmusic/mythmusic/playlist.cpp
===================================================================
--- mythmusic/mythmusic/playlist.cpp	(révision 16138)
+++ mythmusic/mythmusic/playlist.cpp	(copie de travail)
@@ -1,3 +1,6 @@
+#include "playlist.h"
+
+#include <assert.h>
 #include <unistd.h>
 #include <inttypes.h>
 #include <cstdlib>
@@ -4,7 +7,6 @@
 #include <iostream>
 #include <map>
 using namespace std;
-#include "playlist.h"
 #include "qdatetime.h"
 #include <mythtv/mythcontext.h>
 #include "smartplaylist.h"
@@ -921,6 +923,91 @@
     return songlist;
 }
 
+void Playlist::computeIntelliOrder(QPtrList<Track>&        songs,
+                                   std::map<int,uint32_t>& order,
+                                   int                     playcountMin,
+                                   int                     playcountMax,
+                                   double                  lastplayMin,
+                                   double                  lastplayMax)
+{
+    assert(order.empty());
+
+    int RatingWeight = 2;
+    int PlayCountWeight = 2;
+    int LastPlayWeight = 2;
+    int RandomWeight = 2;
+    parent->FillIntelliWeights(RatingWeight, PlayCountWeight, LastPlayWeight,
+                               RandomWeight);
+
+    // first we compute all the weights
+    Track *trackIt;
+    double totalWeights = 0;
+    std::map<int,double> weights;
+    int TotalWeight = RatingWeight + PlayCountWeight + LastPlayWeight;
+    for (trackIt = songs.first(); trackIt; trackIt = songs.next())
+    {
+        if (!trackIt->getCDFlag())
+        {
+            int songId = trackIt->getValue();
+            if (songId == 0)
+            {
+                VERBOSE(VB_IMPORTANT, "Song with ID of 0 in playlist, this "
+                                      "shouldn't happen.");
+            }
+            if (songId > 0)
+            {
+                Metadata *tmpdata = all_available_music->getMetadata(songId);
+                if (tmpdata && tmpdata->isVisible())
+                {
+                    int rating = tmpdata->Rating();
+                    int playcount = tmpdata->PlayCount();
+                    double lastplaydbl = tmpdata->LastPlay();
+                    double ratingValue = (double)(rating) / 10;
+                    double playcountValue, lastplayValue;
+
+                    if (playcountMax == playcountMin) 
+                        playcountValue = 0;
+                    else 
+                        playcountValue = ((playcountMin - (double)playcount) / (playcountMax - playcountMin) + 1);
+
+                    if (lastplayMax == lastplayMin) 
+                        lastplayValue = 0;
+                    else
+                        lastplayValue = ((lastplayMin - lastplaydbl) / (lastplayMax - lastplayMin) + 1);
+
+                    double weight = (RatingWeight * ratingValue +
+                                     PlayCountWeight * playcountValue + 
+                                     LastPlayWeight * lastplayValue) / TotalWeight;
+                    weight *= weight; // reduce even more the low weights, keep higher weights high
+                    weights[songId] = weight;
+                    totalWeights += weight;
+                }
+            }
+        }
+    }
+
+    // then we get a random order, balanced with relative weights of remaining songs
+    uint32_t orderCpt = 1;
+    std::map<int,double>::iterator weightIt, weightEnd;
+    while(weights.size() > 0)
+    {
+        double hit = totalWeights * (double)rand() / (double)RAND_MAX;
+        weightEnd = weights.end();
+        weightIt = weights.begin();
+        double pos = 0;
+        while(weightIt != weightEnd)
+        {
+            pos += weightIt->second;
+            if(pos >= hit) break;
+            ++weightIt;
+        }
+        order[weightIt->first] = orderCpt;
+        totalWeights -= weightIt->second;
+        weights.erase(weightIt);
+        ++orderCpt;
+    }
+}
+
 int Playlist::writeTree(GenericTree *tree_to_write_to, int a_counter)
 {
     Track *it;
@@ -1006,14 +1093,11 @@
         count++;
     }
 
-    int RatingWeight = 2;
-    int PlayCountWeight = 2;
-    int LastPlayWeight = 2;
-    int RandomWeight = 2;
+    std::map<int,uint32_t> intelliOrder;
+    computeIntelliOrder(songs, intelliOrder,
+                        playcountMin, playcountMax,
+                        lastplayMin, lastplayMax);
 
-    parent->FillIntelliWeights(RatingWeight, PlayCountWeight, LastPlayWeight,
-                               RandomWeight);
-
     for (it = songs.first(); it; it = songs.next())
     {
         if (!it->getCDFlag())
@@ -1036,32 +1120,9 @@
                     added_node->setAttribute(1, a_counter); //  regular order
                     added_node->setAttribute(2, rand()); //  random order
 
-                    //
-                    //  Compute "intelligent" weighting
-                    //
+                    //  "intelligent" order
+                    added_node->setAttribute(3, intelliOrder[it->getValue()]);
 
-                    int rating = tmpdata->Rating();
-                    int playcount = tmpdata->PlayCount();
-                    double lastplaydbl = tmpdata->LastPlay();
-                    double ratingValue = (double)(rating) / 10;
-                    double playcountValue, lastplayValue;
-
-                    if (playcountMax == playcountMin) 
-                        playcountValue = 0;
-                    else 
-                        playcountValue = ((playcountMin - (double)playcount) / (playcountMax - playcountMin) + 1);
-
-                    if (lastplayMax == lastplayMin) 
-                        lastplayValue = 0;
-                    else
-                        lastplayValue = ((lastplayMin - lastplaydbl) / (lastplayMax - lastplayMin) + 1);
-
-                    double rating_value =  (RatingWeight * ratingValue + PlayCountWeight * playcountValue + 
-                                            LastPlayWeight * lastplayValue + RandomWeight * (double)rand() / 
-                                            (RAND_MAX + 1.0));
-                    uint32_t integer_rating = (int) (4000001 - rating_value * 10000);
-                    added_node->setAttribute(3, integer_rating); //  "intelligent" order
-
                     // "intellegent/album" order
                     uint32_t album_order;
                     album = tmpdata->Album();
