home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 February / PCWorld_2001-02_cd.bin / Software / Topware / winmedpl / mpbonus_full.exe / wmpskin.cab / DigitalDJ.wmz / query.js < prev    next >
Encoding:
JavaScript  |  2000-07-13  |  50.4 KB  |  1,523 lines

  1. //<script>
  2. //****************************************************************
  3. //  ⌐2000 Microsoft Corporation. All rights reserved.
  4. //****************************************************************
  5. //
  6. // JScript Query Object
  7. //
  8. // This object allows for a skin to query the media library for
  9. // one of many different attributes.
  10. //****************************************************************
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17. //****************************************************************
  18. //****************************************************************
  19. //
  20. // query object
  21. //
  22. //****************************************************************
  23. //****************************************************************
  24.  
  25. function query( progressbar, completeQuery )
  26. {
  27.     // Controls
  28.  
  29.     this.progressbar                    = progressbar;
  30.     
  31.     // Public Properties
  32.     
  33.     this.genre_collection               = null;                                 // A string collection of genres from core
  34.     this.genre_include_array            = new Array();                          // An array (integer based) of genres to include
  35.     this.genre_exclude_array            = new Array();                          // An array (integer based) of genres to exclude
  36.  
  37.     this.artist_collection              = null;                                 // A string collection of artists from core
  38.     this.artist_include_array           = new Array();                          // An array (integer based) of artists to include
  39.     this.artist_exclude_array           = new Array();                          // An array (integer based) of artists to exclude
  40.     
  41.     this.album_collection               = null;                                 // A string collection of albums from core
  42.     this.album_include_array            = new Array();                          // An array (integer based) of albums to include
  43.     this.album_exclude_array            = new Array();                          // An array (integer based) of albums to exclude
  44.     
  45.     this.playlist_collection            = null;                                 // A playlist collection from core
  46.     this.playlist_include_array         = new Array();                          // An array (integer based) of playlists to include
  47.     this.playlist_exclude_array         = new Array();                          // An array (integer based) of playlists to exclude 
  48.     
  49.     this.search_include_array_txt       = new Array();                          // Description for each playlist in the include array
  50.     this.search_include_array_pl        = new Array();                          // Array of playlists to include
  51.     this.search_exclude_array_txt       = new Array();                          // Description for each playlist in the exclude array
  52.     this.search_exclude_array_pl        = new Array();                          // Array of playlist to exclude
  53.     
  54.     this.allow_playlists                = false;                                // True to allow *.m3u and *.asx into the query
  55.     this.allow_urls                     = false;                                // True to allow '://' source URLs into the query
  56.     this.allow_blank                    = false;                                // True to allow blank artist & album metadata into the query
  57.     
  58.     this.playcount_filter               = false;                                // Use the playcount filter?
  59.     this.playcount_filter_comparison    = 0;                                    // Comparison operator - 0 = less than, 1 = equal to, 2 = greater than
  60.     this.playcount_filter_count         = 5;                                    // Value to compare against
  61.  
  62.     this.playcount_favoring             = false;                                // Use playcount favoring when deleting tracks?
  63.     this.playcount_favoring_comparison  = 0;                                    // Comparison operator - 0 = played most often, 1 = played least often
  64.     this.playcount_favoring_sample      = 15;                                   // Number of tracks to sample to do favoring
  65.     
  66.     this.playlength_filter              = false;                                // Use a playlength filter?
  67.     this.playlength_filter_comparison   = 0;                                    // Comparison operator - 0 = at least, 1 = at most
  68.     this.playlength_filter_length       = 30;                                   // Value (in seconds) to compare against
  69.     
  70.     this.generic_search                 = false;                                // Use a generic search?
  71.     this.generic_search_name            = '';                                   // Generic search attribute name to use
  72.     this.generic_search_comparison      = 0;                                    // Comparison operator - 0 = contains, 1 = doesn't contain, 2 = equals, 3 = doesn't equal
  73.     this.generic_search_value           = '';                                   // Value to match search against
  74.     
  75.     this.playlength_limit               = true;                                 // Use a cap on the possible length of the playlist?
  76.     this.playlength_limit_length        = 14400;                                // Value (in seconds) to keep the playlist under (default 4hr)
  77.     
  78.     this.shuffle_playlist               = true;                                 // Do we shuffle the resultant playlist?
  79.     
  80.     this.performing_query               = false;                                // Are we performing the query?
  81.     this.query_aborted                  = false;                                // Has the query been aborted?
  82.  
  83.     this.plQueryResult                  = null;                                 // The resultant query playlist after the query completes
  84.     this.plLibraryResult                = null;                                 // The resultant library playlist (if requested) after the query completes
  85.  
  86.     // Public Methods
  87.     
  88.     this.getGenreCountQ                         = getGenreCountQ;                           // Retrieves the number of genres in the collection
  89.     this.getGenreListQ                          = getGenreListQ;                            // Retrieves a (/r delimited) list of genres in the collection
  90.     this.addGenreIncludeQ                       = addGenreIncludeQ;                         // Adds a genre include to the query (integer based)
  91.     this.addGenreExcludeQ                       = addGenreExcludeQ;                         // Adds a genre exclude to the query (integer based)
  92.  
  93.     this.getArtistCountQ                        = getArtistCountQ;                          // Retrieves the number of artists in the collection
  94.     this.getArtistListQ                         = getArtistListQ;                           // Retrieves a (/r delimited) list of artists in the collection
  95.     this.addArtistIncludeQ                      = addArtistIncludeQ;                        // Adds an artist include to the query (integer based)
  96.     this.addArtistExcludeQ                      = addArtistExcludeQ;                        // Adds an artist exclude ot the query (integer based)
  97.  
  98.     this.getAlbumCountQ                         = getAlbumCountQ;                           // Retrieves the number of albums in the collection
  99.     this.getAlbumListQ                          = getAlbumListQ;                            // Retrieves a (/r delimited) list of albums in the collection
  100.     this.addAlbumIncludeQ                       = addAlbumIncludeQ;                         // Adds an album include to the query (integer based)
  101.     this.addAlbumExcludeQ                       = addAlbumExcludeQ;                         // Adds an album exclude to the query (integer based)
  102.  
  103.     this.getPlaylistCountQ                      = getPlaylistCountQ;                        // Retrieves the number of playlists in the library
  104.     this.getPlaylistListQ                       = getPlaylistListQ;                         // Retrieves a (/r delimited) list of playlists in the library
  105.     this.addPlaylistIncludeQ                    = addPlaylistIncludeQ;                      // Adds a library playlist to include to the query (integer based)
  106.     this.addPlaylistExcludeQ                    = addPlaylistExcludeQ;                      // Adds a library playlist to exclude to the query (integer based)
  107.     
  108.     this.addSearchPlaylistIncludeQ              = addSearchPlaylistIncludeQ;                // Adds a generic playlist (with description) to the query include
  109.     this.addSearchPlaylistExcludeQ              = addSearchPlaylistExcludeQ;                // Adds a genreic playlist (with description) to the query exclude
  110.  
  111.     this.getPlaycountFilterComparisonStringQ    = getPlaycountFilterComparisonStringQ;      // Retrieves a brief description of the playcount comparison string
  112.     this.getPlaycountFavoringComparisonStringQ  = getPlaycountFavoringComparisonStringQ;    // Retrieves a brief description of the playcount favoring string
  113.     this.getPlaylengthFilterComparisonStringQ   = getPlaylengthFilterComparisonStringQ;     // Retrieves a brief description of the playlength comparison string
  114.     this.getGenericSearchComparisonStringQ      = getGenericSearchComparisonStringQ;        // Retrieves a brief description of the search comparison string
  115.     this.getQueryDescriptionQ                   = getQueryDescriptionQ;                     // Retrieves a string description of the query
  116.     
  117.     this.performQueryQ                          = performQueryQ;                            // Starts the query
  118.     this.continueQueryQ                         = continueQueryQ;                           // Continues the query (must be called from progressbar_onendmove)
  119.  
  120.     // Public events
  121.  
  122.     this.completeQuery                          = completeQuery;                            // Event to be notified of the query's completion
  123.  
  124.  
  125.     // Private Member Variables (do not modify)
  126.  
  127.     this.nQueryPosition                 = 0;
  128.  
  129.     this.fConcatenating                 = false;
  130.     this.nConcatIndex                   = 0;
  131.     this.plDest                         = null;
  132.     this.plSource                       = null;
  133.  
  134.     this.plIncludeResult                = null;
  135.     this.plExcludeResult                = null;
  136.  
  137.     this.nQueryIndex                    = 0;
  138.  
  139.     this.rgGenre                        = null;
  140.     this.rgArtist                       = null;
  141.     this.rgAlbum                        = null;
  142.     this.rgPlaylist                     = null;
  143.     this.rgSearch                       = null;
  144.  
  145.     this.nCurrentLength                 = 0;
  146.     this.nOriginalLength                = 0;
  147.     this.nExcludeCount                  = 0;
  148.  
  149.     this.playlistname                   = '';
  150. }
  151.  
  152.  
  153. //****************************************************************
  154. // Genre Operations
  155. //****************************************************************
  156.  
  157. function getGenreCountQ()
  158. {
  159.     if (this.genre_collection == null)
  160.     {
  161.         this.genre_collection = player.mediaCollection.getAttributeStringCollection( "Genre", "Audio" );
  162.     }
  163.     return (this.genre_collection ? this.genre_collection.count : 0);
  164. }
  165.  
  166. //****************************************************************
  167.  
  168. function getGenreListQ()
  169. {
  170.     this.getGenreCountQ();
  171.     if (this.genre_collection == null)
  172.     {
  173.         return '';
  174.     }
  175.     return getStringFromAttributeStringCollection( this.genre_collection );
  176. }
  177.  
  178. //****************************************************************
  179.  
  180. function addGenreIncludeQ( nIndex )
  181. {
  182.     addInclude( nIndex, this.genre_include_array, this.genre_exclude_array );
  183. }
  184.  
  185. //****************************************************************
  186.  
  187. function addGenreExcludeQ( nIndex )
  188. {
  189.     addExclude( nIndex, this.genre_include_array, this.genre_exclude_array );
  190. }
  191.  
  192.  
  193. //****************************************************************
  194. // Artist Operations
  195. //****************************************************************
  196.  
  197. function getArtistCountQ()
  198. {
  199.     if (this.artist_collection == null)
  200.     {
  201.         this.artist_collection = player.mediaCollection.getAttributeStringCollection( "Artist", "Audio" );
  202.     }
  203.     return (this.artist_collection ? this.artist_collection.count : 0);
  204. }
  205.  
  206. //****************************************************************
  207.  
  208. function getArtistListQ()
  209. {
  210.     this.getArtistCountQ();
  211.     if (this.artist_collection == null)
  212.     {
  213.         return '';
  214.     }
  215.     return getStringFromAttributeStringCollection( this.artist_collection );
  216. }
  217.  
  218. //****************************************************************
  219.  
  220. function addArtistIncludeQ( nIndex )
  221. {
  222.     addInclude( nIndex, this.artist_include_array, this.artist_exclude_array );
  223. }
  224.  
  225. //****************************************************************
  226.  
  227. function addArtistExcludeQ( nIndex )
  228. {
  229.     addExclude( nIndex, this.artist_include_array, this.artist_exclude_array );
  230. }
  231.  
  232.  
  233. //****************************************************************
  234. // Album Operations
  235. //****************************************************************
  236.  
  237. function getAlbumCountQ()
  238. {
  239.     if (this.album_collection == null)
  240.     {
  241.         this.album_collection = player.mediaCollection.getAttributeStringCollection( "Album", "Audio" );
  242.     }
  243.     return (this.album_collection ? this.album_collection.count : 0);
  244. }
  245.  
  246. //****************************************************************
  247.  
  248. function getAlbumListQ()
  249. {
  250.     this.getAlbumCountQ();
  251.     if (this.album_collection == null)
  252.     {
  253.         return '';
  254.     }
  255.     return getStringFromAttributeStringCollection( this.album_collection );
  256. }
  257.  
  258. //****************************************************************
  259.  
  260. function addAlbumIncludeQ( nIndex )
  261. {
  262.     addInclude( nIndex, this.album_include_array, this.album_exclude_array );
  263. }
  264.  
  265. //****************************************************************
  266.  
  267. function addAlbumExcludeQ( nIndex )
  268. {
  269.     addExclude( nIndex, this.album_include_array, this.album_exclude_array );
  270. }
  271.  
  272.  
  273. //****************************************************************
  274. // Playlist Operations
  275. //****************************************************************
  276.  
  277. function getPlaylistCountQ()
  278. {
  279.     if (this.playlist_collection == null)
  280.     {
  281.         this.playlist_collection = player.playlistCollection.getAll();
  282.     }
  283.     return (this.playlist_collection ? this.playlist_collection.count : 0);
  284. }
  285.  
  286. //****************************************************************
  287.  
  288. function getPlaylistListQ()
  289. {
  290.     // We need to ensure a refresh, but we also need to make sure
  291.     // our old and new items still line up... if not, then we need
  292.     // to fix them.
  293.  
  294.     var oldList                 = this.playlist_collection;
  295.     this.playlist_collection    = null;
  296.     
  297.     this.getPlaylistCountQ();
  298.     if (this.playlist_collection == null)
  299.     {
  300.         return '';
  301.     }
  302.     
  303.     var string = '';
  304.  
  305.     for (var nIndex = 0; nIndex < this.playlist_collection.count; nIndex++)
  306.     {
  307.         if (string != '')
  308.         {
  309.             string += '\r';
  310.         }
  311.         string += this.playlist_collection.item( nIndex ).name;
  312.     }
  313.     
  314.     if ((oldList != null) && (this.playlist_include_array.length != 0 || this.playlist_exclude_array.length != 0))
  315.     {
  316.         reconcilePlaylistArray( oldList, this.playlist_collection, this.playlist_include_array );
  317.         reconcilePlaylistArray( oldList, this.playlist_collection, this.playlist_exclude_array );
  318.     }
  319.     
  320.     return string;
  321. }
  322.  
  323. //****************************************************************
  324.  
  325. function addPlaylistIncludeQ( nIndex )
  326. {
  327.     addInclude( nIndex, this.playlist_include_array, this.playlist_exclude_array );
  328. }
  329.  
  330. //****************************************************************
  331.  
  332. function addPlaylistExcludeQ( nIndex )
  333. {
  334.     addExclude( nIndex, this.playlist_include_array, this.playlist_exclude_array );
  335. }
  336.  
  337.  
  338. //****************************************************************
  339. // Search Playlist Operations
  340. //****************************************************************
  341.  
  342. function addSearchPlaylistIncludeQ( description, playlist )
  343. {
  344.     if (inArray( description, this.search_include_array_txt ))
  345.     {
  346.         var nPos = arrayPosition( description, this.search_include_array_txt );
  347.         
  348.         removeItemFromArray( this.search_include_array_txt[nPos], this.search_include_array_txt );
  349.         removeItemFromArray( this.search_include_array_pl[nPos], this.search_include_array_pl );
  350.     }
  351.     else 
  352.     {
  353.         if (inArray( description, this.search_exclude_array_txt ))
  354.         {
  355.             // remove it...
  356.             
  357.             this.addSearchPlaylistExcludeQ( description, playlist );
  358.         }
  359.         
  360.         this.search_include_array_txt[ this.search_include_array_txt.length ] = description;
  361.         this.search_include_array_pl[ this.search_include_array_pl.length ] = playlist;
  362.     }
  363. }
  364.  
  365. //****************************************************************
  366.  
  367. function addSearchPlaylistExcludeQ( description, playlist )
  368. {
  369.     if (inArray( description, this.search_exclude_array_txt ))
  370.     {
  371.         var nPos = arrayPosition( description, this.search_exclude_array_txt );
  372.         
  373.         removeItemFromArray( this.search_exclude_array_txt[nPos], this.search_exclude_array_txt );
  374.         removeItemFromArray( this.search_exclude_array_pl[nPos], this.search_exclude_array_pl );
  375.     }
  376.     else 
  377.     {
  378.         if (inArray( description, this.search_include_array_txt ))
  379.         {
  380.             // remove it...
  381.             
  382.             this.addSearchPlaylistIncludeQ( description, playlist );
  383.         }
  384.         
  385.         this.search_exclude_array_txt[ this.search_exclude_array_txt.length ] = description;
  386.         this.search_exclude_array_pl[ this.search_exclude_array_pl.length ] = playlist;
  387.     }
  388. }
  389.  
  390.  
  391. //****************************************************************
  392. // Query Description Methods
  393. //****************************************************************
  394.  
  395. function getPlaycountFilterComparisonStringQ()
  396. {
  397.     switch (this.playcount_filter_comparison)
  398.     {
  399.     case 0:
  400.         return 'less than';
  401.     case 1:
  402.         return 'equal to';
  403.     case 2:
  404.         return 'greater than';
  405.     }
  406. }
  407.  
  408. //****************************************************************
  409.  
  410. function getPlaycountFavoringComparisonStringQ()
  411. {
  412.     switch (this.playcount_favoring_comparison)
  413.     {
  414.     case 0:
  415.         return 'most';
  416.     case 1:
  417.         return 'least';
  418.     }
  419. }
  420.  
  421. //****************************************************************
  422.  
  423. function getPlaylengthFilterComparisonStringQ()
  424. {
  425.     switch (this.playlength_filter_comparison)
  426.     {
  427.     case 0:
  428.         return 'at least';
  429.     case 1:
  430.         return 'at most';
  431.     }
  432. }
  433.  
  434. //****************************************************************
  435.  
  436. function getGenericSearchComparisonStringQ()
  437. {
  438.     switch (this.generic_search_comparison)
  439.     {
  440.     case 0:
  441.         return 'contains';
  442.     case 1:
  443.         return 'doesn\'t contain';
  444.     case 2:
  445.         return 'equals';
  446.     case 3:
  447.         return 'doesn\'t equal';
  448.     }
  449. }
  450.  
  451. //****************************************************************
  452.  
  453. function getQueryDescriptionQ()
  454. {
  455.     var string  = 'Add (Include):';
  456.     var nAdded  = 0;
  457.  
  458.     for (var nIndex = 0; nIndex < this.genre_include_array.length; nIndex++)
  459.     {
  460.         string += '\r    Genre: ' + this.genre_collection.item( this.genre_include_array[nIndex] );
  461.         nAdded++;
  462.     }
  463.     for (var nIndex = 0; nIndex < this.artist_include_array.length; nIndex++)
  464.     {
  465.         string += '\r    Artist: ' + this.artist_collection.item( this.artist_include_array[nIndex] );
  466.         nAdded++;
  467.     }
  468.     for (var nIndex = 0; nIndex < this.album_include_array.length; nIndex++)
  469.     {
  470.         string += '\r    Album: ' + this.album_collection.item( this.album_include_array[nIndex] );
  471.         nAdded++;
  472.     }
  473.     for (var nIndex = 0; nIndex < this.playlist_include_array.length; nIndex++)
  474.     {
  475.         string += '\r    Playlist: ' + this.playlist_collection.item( this.playlist_include_array[nIndex] ).name;
  476.         nAdded++;
  477.     }
  478.     for (var nIndex = 0; nIndex < this.search_include_array_txt.length; nIndex++)
  479.     {
  480.         string += '\r    Search: ' + this.search_include_array_txt[nIndex];
  481.         nAdded++;
  482.     }
  483.  
  484.     if (nAdded == 0)
  485.     {
  486.         if (this.playlength_limit)
  487.         {
  488.             string += '\r    Any Track';
  489.         }
  490.         else
  491.         {
  492.             string += '\r    All Tracks';
  493.         }
  494.     }
  495.  
  496.     string += '\r\r\Leave out (Exclude):';
  497.     nAdded = 0;
  498.  
  499.     for (var nIndex = 0; nIndex < this.genre_exclude_array.length; nIndex++)
  500.     {
  501.         string += '\r    Genre: ' + this.genre_collection.item( this.genre_exclude_array[nIndex] );
  502.         nAdded++;
  503.     }
  504.     for (var nIndex = 0; nIndex < this.artist_exclude_array.length; nIndex++)
  505.     {
  506.         string += '\r    Artist: ' + this.artist_collection.item( this.artist_exclude_array[nIndex] );
  507.         nAdded++;
  508.     }
  509.     for (var nIndex = 0; nIndex < this.album_exclude_array.length; nIndex++)
  510.     {
  511.         string += '\r    Album: ' + this.album_collection.item( this.album_exclude_array[nIndex] );
  512.         nAdded++;
  513.     }
  514.     for (var nIndex = 0; nIndex < this.playlist_exclude_array.length; nIndex++)
  515.     {
  516.         string += '\r    Playlist: ' + this.playlist_collection.item( this.playlist_exclude_array[nIndex] ).name;
  517.         nAdded++;
  518.     }
  519.     for (var nIndex = 0; nIndex < this.search_exclude_array_txt.length; nIndex++)
  520.     {
  521.         string += '\r    Search: ' + this.search_exclude_array_txt[nIndex];
  522.         nAdded++;
  523.     }
  524.  
  525.     if (nAdded == 0)
  526.     {
  527.         string += '\r    Nothing';    
  528.     }
  529.  
  530.     if (    this.playlength_limit || 
  531.             this.allow_playlists || 
  532.             this.allow_urls || 
  533.             this.allow_blank || 
  534.             this.playcount_filter || 
  535.             this.playlength_filter || 
  536.             this.generic_search         )
  537.     {
  538.         string += '\r\r\Additional Options:';
  539.  
  540.         if (this.playlength_limit)
  541.         {
  542.             string += '\r    Length limit: ' + formatMinutesString( this.playlength_limit_length );
  543.             
  544.             if (this.playcount_favoring)
  545.             {
  546.                 string += '\r    Favor ' + this.getPlaycountFavoringComparisonStringQ() + ' played tracks';
  547.             }    
  548.         }
  549.         if (this.allow_playlists)
  550.         {
  551.             string += '\r    Allow nested playlists';    
  552.         }
  553.         if (this.allow_urls)
  554.         {
  555.             string += '\r    Allow URLs';
  556.         }
  557.         if (this.allow_blank)
  558.         {
  559.             string += '\r    Allow blank artist/album';
  560.         }
  561.         if (this.playcount_filter)
  562.         {
  563.             string += '\r    Playcount ' + this.getPlaycountFilterComparisonStringQ() + ' ' + this.playcount_filter_count;
  564.         }
  565.         if (this.playlength_filter)
  566.         {
  567.             string += '\r    Duration ' + this.getPlaylengthFilterComparisonStringQ() + ' ' + formatSecondsString( this.playlength_filter_length );
  568.         }
  569.         if (this.generic_search)
  570.         {
  571.             string += '\r    ' + this.generic_search_name + ' ' + this.getGenericSearchComparisonStringQ() + ' ' + this.generic_search_value;
  572.         }
  573.     }
  574.     
  575.     return string;
  576. }
  577.  
  578.  
  579. //****************************************************************
  580. // Perform the Query
  581. //****************************************************************
  582.  
  583. function performQueryQ( playlistname )
  584. {
  585.     // This function does not complete its work completely
  586.     // synchronously.  So, we need to keep someone from re-entering
  587.     // us while we're in the middle of performing the query.
  588.  
  589.     if (this.performing_query)
  590.     {
  591.         return;
  592.     }
  593.  
  594.     // Set us up for performing the query
  595.  
  596.     this.performing_query   = true;
  597.     this.query_aborted      = false;
  598.     
  599.     // We need to setup our UI to perform the query
  600.     
  601.     this.progressbar.min        = 0;
  602.     this.progressbar.max        =   1 +                                     // include / exclude intersection
  603.                                     1 +                                     // filtering options
  604.                                     (this.playlength_limit ? 1 : 0) +       // playcount filtering ?
  605.                                     (this.playlistname != '' ? 1 : 0) +     // library playlist save ?
  606.                                     (this.shuffle_playlist ? 1 : 0) +       // shuffling ?
  607.                                     (     
  608.                                         this.genre_include_array.length     + this.genre_exclude_array.length +
  609.                                         this.artist_include_array.length    + this.artist_exclude_array.length +
  610.                                         this.album_include_array.length     + this.album_exclude_array.length +
  611.                                         this.playlist_include_array.length  + this.playlist_exclude_array.length +
  612.                                         this.search_include_array_pl.length + this.search_exclude_array_pl.length
  613.                                     );
  614.     this.progressbar.value      = 0;
  615.     
  616.     this.generic_search_value   = this.generic_search_value.toLowerCase();
  617.  
  618.     this.playlistname           = playlistname;    
  619.     this.nQueryPosition         = 0;
  620.     this.continueQueryQ();
  621. }
  622.  
  623. //****************************************************************
  624.  
  625. function continueQueryQ()
  626. {
  627.     xxxDoQuery( this );
  628.  
  629.     if (this.nQueryPosition < 100)
  630.     {
  631.         this.progressbar.moveTo( this.progressbar.left, this.progressbar.top, 10 );    
  632.     }
  633. }
  634.  
  635.  
  636. //****************************************************************
  637. // Private non-member functions that perform the query
  638. //****************************************************************
  639.  
  640. function xxxDoQuery( query )
  641. {
  642.     if (query.query_aborted)
  643.     {
  644.         xxxCompleteQuery( query );
  645.         return;
  646.     }
  647.  
  648.     if (query.fConcatenating)
  649.     {
  650.         xxxContinueConcat( query );
  651.         return;
  652.     }
  653.     
  654.     switch (query.nQueryPosition)
  655.     {
  656.     case 0:
  657.         xxxSetupForIncludePlaylist( query );
  658.         break;
  659.  
  660.     case 1:
  661.         xxxDoGenreQuery( query );
  662.         break;
  663.     
  664.     case 2:
  665.         xxxDoArtistQuery( query );
  666.         break;
  667.    
  668.     case 3:
  669.         xxxDoAlbumQuery( query );
  670.         break;
  671.     
  672.     case 4:
  673.         xxxEnsureQueryPlaylistExists( query );
  674.         break;
  675.         
  676.     case 5:
  677.         xxxCollectLibraryPlaylists( query );
  678.         break;
  679.         
  680.     case 6:
  681.         xxxCollectSearchPlaylists( query );
  682.         break;
  683.         
  684.     case 7:
  685.         xxxSetupForExcludePlaylist( query );
  686.         break;
  687.         
  688.     case 8:
  689.         xxxRemoveExcludeIntersection( query );
  690.         break;
  691.  
  692.     case 9:
  693.         xxxRemoveFilteringOptions( query );
  694.         break;
  695.                 
  696.     case 10:
  697.         xxxMatchLengthLimit( query );
  698.         break;
  699.  
  700.     case 11:
  701.         xxxShufflePlaylist( query );
  702.         break;
  703.         
  704.     case 12:
  705.         xxxPrepareLibraryPlaylist( query );
  706.         break;
  707.         
  708.     case 13:
  709.         xxxSaveLibraryPlaylist( query );
  710.         break;
  711.         
  712.     case 14:
  713.         xxxCompleteQuery( query );
  714.         break;
  715.     }
  716. }
  717.  
  718. //****************************************************************
  719.  
  720. function xxxConcatPlaylists( query, dest_playlist, source_playlist )
  721. {
  722.     query.nConcatIndex      = 0;
  723.     query.plDest            = dest_playlist;
  724.     query.plSource          = source_playlist;
  725.     query.fConcatenating    = true;
  726.     xxxContinueConcat( query );
  727. }
  728.  
  729. //****************************************************************
  730.  
  731. function xxxContinueConcat( query )
  732. {
  733.     var nMaxIterate = 100;
  734.     
  735.     while (query.nConcatIndex < query.plSource.count)
  736.     {
  737.         if (--nMaxIterate <= 0)
  738.         {
  739.             return;
  740.         }
  741.     
  742.         var item = query.plSource.item( query.nConcatIndex++ );
  743.         
  744.         // We'd like to use item.isMemberOf( query.plDest ) here,
  745.         // but it doesn't work quite right for base playlists.
  746.         // So we have to do this by hand...
  747.  
  748.         var fFound = false;        
  749.         for (var nIndex = 0; nIndex < query.plDest.count; nIndex++)
  750.         {
  751.             if (item.isIdentical( query.plDest.item(nIndex) ))
  752.             {
  753.                 fFound = true;
  754.                 break;            
  755.             }        
  756.         }        
  757.         if (!fFound)
  758.         {
  759.             query.plDest.appendItem( item );
  760.         }
  761.     }
  762.  
  763.     query.plDest            = null;
  764.     query.plSource          = null;
  765.     query.fConcatenating    = false;
  766. }
  767.  
  768. //****************************************************************
  769.  
  770. function xxxSetupForIncludePlaylist( query )
  771. {
  772.     query.plQueryResult         = null;
  773.     query.plIncludeResult       = null;
  774.     query.rgGenre               = query.genre_include_array;
  775.     query.rgArtist              = query.artist_include_array;
  776.     query.rgAlbum               = query.album_include_array;
  777.     query.rgPlaylist            = query.playlist_include_array;
  778.     query.rgSearch              = query.search_include_array_pl;
  779.     
  780.     query.nQueryIndex           = 0;
  781.     query.nQueryPosition++;
  782. }
  783.  
  784. //****************************************************************
  785.  
  786. function xxxDoGenreQuery( query )
  787. {
  788.     while (query.nQueryIndex < query.rgGenre.length)
  789.     {
  790.         query.progressbar.value = Math.floor(query.progressbar.value) + 1;
  791.  
  792.         var newPl = player.mediaCollection.getByGenre( query.genre_collection.item( query.rgGenre[ query.nQueryIndex++ ] ) );
  793.  
  794.         if (query.plQueryResult == null)
  795.         {
  796.             query.plQueryResult = newPl;
  797.         }
  798.         else
  799.         {
  800.             xxxConcatPlaylists( query, query.plQueryResult, newPl );
  801.             return;
  802.         }
  803.     }
  804.  
  805.     query.nQueryIndex = 0;
  806.     query.nQueryPosition++;
  807. }
  808.  
  809. //****************************************************************
  810.  
  811. function xxxDoArtistQuery( query )
  812. {
  813.     while (query.nQueryIndex < query.rgArtist.length)
  814.     {
  815.         query.progressbar.value = Math.floor(query.progressbar.value) + 1;
  816.  
  817.         var newPl = player.mediaCollection.getByAttribute( "Artist", query.artist_collection.item( query.rgArtist[ query.nQueryIndex++ ] ) );
  818.  
  819.         if (query.plQueryResult == null)
  820.         {
  821.             query.plQueryResult = newPl;
  822.         }
  823.         else
  824.         {
  825.             xxxConcatPlaylists( query, query.plQueryResult, newPl );
  826.             return;
  827.         }
  828.     }
  829.  
  830.     query.nQueryIndex = 0;
  831.     query.nQueryPosition++;
  832. }
  833.  
  834. //****************************************************************
  835.  
  836. function xxxDoAlbumQuery( query )
  837. {
  838.     while (query.nQueryIndex < query.rgAlbum.length)
  839.     {
  840.         query.progressbar.value = Math.floor(query.progressbar.value) + 1;
  841.  
  842.         var newPl = player.mediaCollection.getByAlbum( query.album_collection.item( query.rgAlbum[ query.nQueryIndex++ ] ) );
  843.  
  844.         if (query.plQueryResult == null)
  845.         {
  846.             query.plQueryResult = newPl;
  847.         }
  848.         else
  849.         {
  850.             xxxConcatPlaylists( query, query.plQueryResult, newPl );
  851.             return;
  852.         }
  853.     }
  854.  
  855.     query.nQueryIndex = 0;
  856.     query.nQueryPosition++;
  857. }
  858.  
  859. //****************************************************************
  860.  
  861. function xxxEnsureQueryPlaylistExists( query )
  862. {
  863.     // At this point, we need to ensure that plQueryResult contains
  864.     // a valid query playlist.  We do this by performing a dummy
  865.     // query if necessary.
  866.  
  867.     if (query.plQueryResult == null)
  868.     {
  869.         // if we're trying to form the include playlist, then we'll
  870.         // want a playlist consisting of all media if we have nothing
  871.         // specifically to include
  872.     
  873.         if (query.plIncludeResult == null)
  874.         {
  875.             if ((query.rgPlaylist.length == 0) && (query.rgSearch.length == 0))
  876.             {
  877.                 query.plQueryResult = player.mediaCollection.getByAttribute( "MediaType", "Audio" );
  878.             }
  879.         }
  880.         
  881.         // if we're the exclude playlist, or we've got things to add to
  882.         // the include playlist, then we just want an empty playlist to
  883.         // work with... so we do a silly query to get us an empty one.
  884.         
  885.         if (query.plQueryResult == null)
  886.         {
  887.             query.plQueryResult = player.mediaCollection.getByAlbum( "xxx_foo_i_dont_exist_xxx" );
  888.         }
  889.     }
  890.     
  891.     query.nQueryIndex = 0;
  892.     query.nQueryPosition++;
  893. }
  894.  
  895. //****************************************************************
  896.  
  897. function xxxCollectLibraryPlaylists( query )
  898. {
  899.     while (query.nQueryIndex < query.rgPlaylist.length)
  900.     {
  901.         query.progressbar.value = Math.floor(query.progressbar.value) + 1;
  902.  
  903.         var newPl = query.playlist_collection.item( query.rgPlaylist[ query.nQueryIndex++ ] );
  904.  
  905.         xxxConcatPlaylists( query, query.plQueryResult, newPl );
  906.         return;
  907.     }
  908.  
  909.     query.nQueryIndex = 0;
  910.     query.nQueryPosition++;
  911. }
  912.  
  913. //****************************************************************
  914.  
  915. function xxxCollectSearchPlaylists( query )
  916. {
  917.     while (query.nQueryIndex < query.rgSearch.length)
  918.     {
  919.         query.progressbar.value = Math.floor(query.progressbar.value) + 1;
  920.  
  921.         xxxConcatPlaylists( query, query.plQueryResult, query.rgSearch[ query.nQueryIndex++ ] );
  922.         return;
  923.     }
  924.     
  925.     query.nQueryIndex = 0;
  926.     query.nQueryPosition++;
  927. }
  928.  
  929. //****************************************************************
  930.  
  931. function xxxSetupForExcludePlaylist( query )
  932. {
  933.     // OK, so we've just finished collecting us a search results
  934.     // playlist.  We now need to see if that playlist was an include
  935.     // or an exclude playlist and do the appropriate thing for both.
  936.     
  937.     if (query.plIncludeResult == null)
  938.     {
  939.         query.plIncludeResult       = query.plQueryResult;
  940.         query.plQueryResult         = null;
  941.         query.plExcludeResult       = null;
  942.         query.rgGenre               = query.genre_exclude_array;
  943.         query.rgArtist              = query.artist_exclude_array;
  944.         query.rgAlbum               = query.album_exclude_array;
  945.         query.rgPlaylist            = query.playlist_exclude_array;
  946.         query.rgSearch              = query.search_exclude_array_pl;
  947.  
  948.         // now reset the query position back to 1 so we wrap
  949.         // back around and form a new query playlist for the exclude
  950.         // side of things
  951.         
  952.         query.nQueryPosition        = 1;
  953.         return;
  954.     }
  955.     
  956.     query.plExcludeResult       = query.plQueryResult;
  957.     query.plQueryResult         = null;
  958.     query.nExcludeCount         = query.plExcludeResult.count;
  959.     
  960.     query.nQueryIndex = 0;
  961.     query.nQueryPosition++;
  962. }
  963.  
  964. //****************************************************************
  965.  
  966. function xxxRemoveExcludeIntersection( query )
  967. {
  968.     var nMaxIterate = 100;
  969.  
  970.     while (query.plExcludeResult.count > 0)
  971.     {
  972.         if (--nMaxIterate <= 0)
  973.         {
  974.             query.progressbar.value = Math.floor(query.progressbar.value) + (query.nQueryIndex / nExcludeCount);
  975.             return;        
  976.         }
  977.  
  978.         query.nQueryIndex++;
  979.  
  980.         // We must remove the item from the playlist in order to get
  981.         // isMemberOf to function properly.  We want to use this
  982.         // method rather than looping through the items directly
  983.  
  984.         var item = query.plExcludeResult.item( query.plExcludeResult.count - 1 );
  985.         query.plExcludeResult.removeItem( item );
  986.         
  987.         if (item.isMemberOf( query.plIncludeResult ))
  988.         {
  989.             query.plIncludeResult.removeItem( item );        
  990.         }
  991.     }
  992.  
  993.     query.plExcludeResult   = null;
  994.     query.progressbar.value    = Math.floor(query.progressbar.value) + 1;
  995.     
  996.     query.nQueryIndex = 0;
  997.     query.nQueryPosition++;
  998. }
  999.  
  1000. //****************************************************************
  1001.  
  1002. function xxxRemoveFilteringOptions( query )
  1003. {
  1004.     var nMaxIterate = 100;
  1005.     
  1006.     while (query.nQueryIndex < query.plIncludeResult.count)
  1007.     {
  1008.         if (--nMaxIterate <= 0)
  1009.         {
  1010.             query.progressbar.value = Math.floor(query.progressbar.value) + (query.nQueryIndex / query.plIncludeResult.count);
  1011.             return;        
  1012.         }
  1013.  
  1014.         var item = query.plIncludeResult.item( query.nQueryIndex );
  1015.  
  1016.         // Remove playlists and urls
  1017.         
  1018.         if (!query.allow_playlists || !query.allow_urls)
  1019.         {
  1020.             var url = new String( item.sourceURL );
  1021.             
  1022.             if (    (!query.allow_playlists && ((-1 != url.search( 'asx$' )) || (-1 != url.search( 'm3u$' )))) ||
  1023.                     (!query.allow_urls && (-1 != url.search( '://' ))) )
  1024.             {
  1025.                 query.plIncludeResult.removeItem( item );
  1026.                 continue;
  1027.             }
  1028.         }
  1029.         
  1030.         // Remove blank metadata        
  1031.         
  1032.         if (!query.allow_blank)
  1033.         {
  1034.             if (('' == item.getItemInfo('Artist')) && ('' == item.getItemInfo('Album')))
  1035.             {
  1036.                 query.plIncludeResult.removeItem( item );
  1037.                 continue;
  1038.             }
  1039.         }
  1040.  
  1041.         // Remove items not matching our playcount specification
  1042.         
  1043.         if (query.playcount_filter)
  1044.         {
  1045.             var count = item.getItemInfo( 'PlayCount' );
  1046.  
  1047.             if (    (query.playcount_filter_comparison == 0 && query.playcount_filter_count <= count) ||
  1048.                     (query.playcount_filter_comparison == 1 && query.playcount_filter_count != count) ||
  1049.                     (query.playcount_filter_comparison == 2 && query.playcount_filter_count >= count)     )
  1050.             {
  1051.                 query.plIncludeResult.removeItem( item );
  1052.                 continue;
  1053.             }
  1054.         }
  1055.  
  1056.         // Remove items not matching our play length specification
  1057.  
  1058.         if (query.playlength_filter)
  1059.         {
  1060.             var duration = item.duration;
  1061.             
  1062.             if (    (query.playlength_filter_comparison == 0 && duration <= query.playlength_filter_length) ||
  1063.                     (query.playlength_filter_comparison == 1 && duration >= query.playlength_filter_length)      )
  1064.             {
  1065.                 query.plIncludeResult.removeItem( item );
  1066.                 continue;
  1067.             }
  1068.         }
  1069.  
  1070.         if (query.generic_search)
  1071.         {
  1072.             var attrib = item.getItemInfo( query.generic_search_name );
  1073.             var sval = new String( attrib.toLowerCase() );
  1074.             
  1075.             if (    (query.generic_search_comparison == 0 && (-1 == sval.search( query.generic_search_value ))) ||
  1076.                     (query.generic_search_comparison == 1 && (-1 != sval.search( query.generic_search_value ))) ||
  1077.                     (query.generic_search_comparison == 2 && (sval != query.generic_search_value)) ||
  1078.                     (query.generic_search_comparison == 3 && (sval == query.generic_search_value))        )
  1079.             {
  1080.                 query.plIncludeResult.removeItem( item );
  1081.                 continue;
  1082.             }
  1083.         }
  1084.         
  1085.         // we'll keep this one
  1086.  
  1087.         query.nQueryIndex++;
  1088.     }
  1089.  
  1090.     // now that we've removed everything we want to, get an initial length
  1091.     // from the playlist so that we may do length limiting
  1092.     
  1093.     query.nCurrentLength    = getPlaylistLength( query.plIncludeResult );
  1094.     query.nOriginalLength   = query.nCurrentLength;
  1095.  
  1096.     query.progressbar.value    = Math.floor(query.progressbar.value) + 1;
  1097.  
  1098.     query.nQueryIndex = 0;
  1099.     query.nQueryPosition++;
  1100. }
  1101.  
  1102. //****************************************************************
  1103.  
  1104. function xxxMatchLengthLimit( query )
  1105. {
  1106.     if (query.playlength_limit)
  1107.     {
  1108.         var nMaxIterate = 25;
  1109.         
  1110.         while (query.nCurrentLength > query.playlength_limit_length)
  1111.         {
  1112.             if (--nMaxIterate <= 0)
  1113.             {
  1114.                 query.progressbar.value = Math.floor(query.progressbar.value) + ((query.nOriginalLength - query.nCurrentLength) / (query.nOriginalLength - query.playlength_limit_length));
  1115.                 return;
  1116.             }
  1117.             
  1118.             var nDelIndex = 0;
  1119.             
  1120.             if (query.playcount_favoring)
  1121.             {
  1122.                 // for playcount favoring we take a sample of items to pick the item to
  1123.                 // delete.  We then delete the one with the highest (or lowest)
  1124.                 // playcount avaialable.
  1125.             
  1126.                 var rgPlaycount = new Array();
  1127.                 var rgIndex     = new Array();
  1128.                 var nMax        = 0;
  1129.                 
  1130.                 for (var nIndex = 0; nIndex < query.playcount_favoring_sample; nIndex++)
  1131.                 {
  1132.                     rgIndex[nIndex] = rand( query.plIncludeResult.count );
  1133.                     rgPlaycount[nIndex] = query.plIncludeResult.item( rgIndex[nIndex] ).getItemInfo( 'PlayCount' );
  1134.                 }
  1135.  
  1136.                 var nSelection = 0;
  1137.                 
  1138.                 for (var nIndex = 1; nIndex < rgPlaycount.length; nIndex++)
  1139.                 {
  1140.                     if (    (query.playcount_favoring_comparison == 0 && rgPlaycount[nIndex] < rgPlaycount[nSelection]) ||
  1141.                             (query.playcount_favoring_comparison == 1 && rgPlaycount[nIndex] > rgPlaycount[nSelection]) )
  1142.                     {
  1143.                         nSelection = nIndex;
  1144.                     }
  1145.                 }
  1146.                 
  1147.                 nDelIndex = rgIndex[ nSelection ];
  1148.             }
  1149.             else
  1150.             {
  1151.                 nDelIndex = rand( query.plIncludeResult.count );
  1152.             }
  1153.  
  1154.             var item = query.plIncludeResult.item( nDelIndex );
  1155.             query.nCurrentLength -= item.duration;
  1156.             query.plIncludeResult.removeItem( item );
  1157.         }   
  1158.  
  1159.         query.progressbar.value    = Math.floor(query.progressbar.value) + 1;
  1160.     }
  1161.     
  1162.     query.nQueryIndex = 0;
  1163.     query.nQueryPosition++;
  1164. }
  1165.  
  1166. //****************************************************************
  1167.  
  1168. function xxxShufflePlaylist( query )
  1169. {
  1170.     if (query.shuffle_playlist)
  1171.     {
  1172.         var nMaxIterate = 100;
  1173.  
  1174.         while (query.nQueryIndex < (query.plIncludeResult.count * 2))
  1175.         {
  1176.             if (--nMaxIterate <= 0)
  1177.             {
  1178.                 query.progressbar.value = Math.floor(query.progressbar.value) + (query.nQueryIndex / (query.plIncludeResult.count * 2));
  1179.                 return;
  1180.             }        
  1181.             
  1182.             query.plIncludeResult.moveItem( rand(query.plIncludeResult.count), rand(query.plIncludeResult.count) );
  1183.             query.nQueryIndex++;
  1184.         }
  1185.         
  1186.         query.progressbar.value    = Math.floor(query.progressbar.value) + 1;
  1187.     }
  1188.     
  1189.     query.nQueryIndex = 0;
  1190.     query.nQueryPosition++;
  1191. }
  1192.  
  1193. //****************************************************************
  1194.  
  1195. function xxxPrepareLibraryPlaylist( query )
  1196. {
  1197.     query.plLibraryResult   = null;
  1198.  
  1199.     if (query.playlistname != '')
  1200.     {
  1201.         query.plLibraryResult = getLibraryPlaylist( query.playlistname );
  1202.         
  1203.         if (query.plLibraryResult != null)
  1204.         {
  1205.             // If this is the playlist on core, then we need to make
  1206.             // sure that an empty playlist is thrown on core to avoid
  1207.             // being overwhelmed with playlist rebuilding while we make
  1208.             // changes.
  1209.         
  1210.             if (!player.currentPlaylist || query.plLibraryResult.isIdentical( player.currentPlaylist ))
  1211.             {
  1212.                 player.currentPlaylist = player.mediaCollection.getByAlbum( "xxx_foo_i_dont_exist_xxx" );
  1213.             }
  1214.         
  1215.             player.playlistCollection.remove( query.plLibraryResult );
  1216.             query.plLibraryResult = null;
  1217.         }
  1218.     }
  1219.     
  1220.     query.nQueryIndex = 0;
  1221.     query.nQueryPosition++;
  1222. }
  1223.  
  1224. //****************************************************************
  1225.  
  1226. function xxxSaveLibraryPlaylist( query )
  1227. {
  1228.     if (query.playlistname != '')
  1229.     {
  1230.         query.plIncludeResult.name  = query.playlistname;
  1231.         query.plLibraryResult       = player.playlistCollection.importPlaylist( query.plIncludeResult );
  1232.         
  1233.         query.progressbar.value    = Math.floor(query.progressbar.value) + 1;
  1234.     }
  1235.     
  1236.     query.nQueryIndex = 0;
  1237.     query.nQueryPosition++;
  1238. }
  1239.  
  1240. //****************************************************************
  1241.  
  1242. function xxxCompleteQuery( query )
  1243. {
  1244.     query.progressbar.value     = query.progressbar.max;
  1245.     
  1246.     // max out query position to end the query
  1247.  
  1248.     query.plQueryResult     = query.plIncludeResult;
  1249.     query.plIncludeResult   = null;
  1250.     query.plExcludeResult   = null;
  1251.     query.performing_query  = false;
  1252.     query.nQueryPosition    = 1000;
  1253.     
  1254.     if (query.completeQuery)
  1255.     {
  1256.         query.completeQuery();
  1257.     }
  1258. }
  1259.  
  1260.  
  1261.  
  1262.  
  1263.  
  1264.  
  1265.  
  1266.  
  1267.  
  1268.  
  1269.  
  1270.  
  1271.  
  1272.  
  1273. //****************************************************************
  1274. // utility functions
  1275. //****************************************************************
  1276.  
  1277. function getStringFromAttributeStringCollection( collection )
  1278. {
  1279.     var string = '';
  1280.  
  1281.     for (var nIndex = 0; nIndex < collection.count; nIndex++)
  1282.     {
  1283.         if (string != '')
  1284.         {
  1285.             string += '\r';
  1286.         }
  1287.         string += collection.item( nIndex );
  1288.     }
  1289.  
  1290.     return string;
  1291. }
  1292.  
  1293. //****************************************************************
  1294.  
  1295. function inArray( nValue, array )
  1296. {
  1297.     var i = 0;
  1298.     while (i < array.length)
  1299.     {
  1300.         if (array[i++] == nValue)
  1301.         {
  1302.             return true;
  1303.         }
  1304.     }
  1305.     return false;
  1306. }
  1307.  
  1308. //****************************************************************
  1309.  
  1310. function arrayPosition( nValue, array )
  1311. {
  1312.     var i = 0;
  1313.     while (i < array.length)
  1314.     {
  1315.         if (array[i++] == nValue)
  1316.         {
  1317.             return (i-1);
  1318.         }
  1319.     }
  1320.     return -1;
  1321. }
  1322.  
  1323. //****************************************************************
  1324.  
  1325. function removeItemFromArray( nValue, array )
  1326. {
  1327.     var i = 0;
  1328.     while (i < array.length)
  1329.     {
  1330.         if (array[i++] == nValue)
  1331.         {
  1332.             while (i < array.length)
  1333.             {
  1334.                 array[i - 1] = array[i];
  1335.                 i++;
  1336.             }
  1337.             break;
  1338.         }
  1339.     }
  1340.     array.length = (array.length - 1);
  1341. }
  1342.  
  1343. //****************************************************************
  1344.  
  1345. function addInclude( nIndex, include_array, exclude_array )
  1346. {
  1347.     if (inArray( nIndex, include_array ))
  1348.     {
  1349.         removeItemFromArray( nIndex, include_array );    
  1350.     }
  1351.     else 
  1352.     {
  1353.         if (inArray( nIndex, exclude_array ))
  1354.         {
  1355.             removeItemFromArray( nIndex, exclude_array );
  1356.         }
  1357.         include_array[ include_array.length ] = nIndex;
  1358.     }
  1359. }
  1360.  
  1361. //****************************************************************
  1362.  
  1363. function addExclude( nIndex, include_array, exclude_array )
  1364. {
  1365.     if (inArray( nIndex, exclude_array ))
  1366.     {
  1367.         removeItemFromArray( nIndex, exclude_array );    
  1368.     }
  1369.     else 
  1370.     {
  1371.         if (inArray( nIndex, include_array ))
  1372.         {
  1373.             removeItemFromArray( nIndex, include_array );
  1374.         }
  1375.         exclude_array[ exclude_array.length ] = nIndex;
  1376.     }
  1377. }
  1378.  
  1379. //****************************************************************
  1380. // This function is a utility function used to return a readable
  1381. // string from a number of seconds (basically a duration string)
  1382.  
  1383. function formatSecondsString( seconds )
  1384. {
  1385.     var str = '';
  1386.  
  1387.     var hours   = Math.floor( seconds / (60 * 60) );
  1388.     var minutes = Math.floor( (seconds - (hours * 60 * 60)) / 60 );
  1389.     var seconds = Math.floor( seconds % 60 );
  1390.  
  1391.     if (hours > 0)
  1392.     {
  1393.         str += hours + ':';
  1394.         if (minutes < 10)
  1395.         {
  1396.             str += '0';
  1397.         }
  1398.     }
  1399.     str += minutes + ':';
  1400.     if (seconds < 10)
  1401.     {
  1402.         str += '0';
  1403.     }
  1404.     str += seconds;
  1405.  
  1406.     return str;
  1407. }
  1408.  
  1409. //****************************************************************
  1410. // This function is a utility function used to return a readable
  1411. // string from a number of seconds (basically a duration string)
  1412.  
  1413. function formatMinutesString( seconds )
  1414. {
  1415.     var str = '';
  1416.  
  1417.     var hours   = Math.floor( seconds / (60 * 60) );
  1418.     var minutes = Math.floor( (seconds - (hours * 60 * 60)) / 60 );
  1419.  
  1420.     if (hours > 0)
  1421.     {
  1422.         str += hours + ' hr';
  1423.         if (minutes > 0)
  1424.         {
  1425.             str += ' ';
  1426.         }
  1427.     }
  1428.     
  1429.     if (minutes > 0)
  1430.     {
  1431.         str += minutes + ' min';
  1432.     }
  1433.  
  1434.     return str;
  1435. }
  1436.  
  1437. //****************************************************************
  1438. // This is a simple function designed to return the length (in
  1439. // seconds) of a given playlist
  1440.  
  1441. function getPlaylistLength( playlist )
  1442. {
  1443.     var plLength = 0;
  1444.  
  1445.     for (var nIndex = 0; nIndex < playlist.count; nIndex++)
  1446.     {
  1447.         plLength += playlist.item(nIndex).duration;
  1448.     }
  1449.  
  1450.     return plLength;
  1451. }
  1452.  
  1453.  
  1454. //****************************************************************
  1455. // This function allows fetching of a random number
  1456.  
  1457. var now     = new Date();
  1458. var seed    = now.getTime() % 0xffffffff;
  1459.  
  1460. function rand(n)
  1461. {
  1462.     seed = (0x015a4e35 * seed) % 0x7fffffff;
  1463.     return (seed >> 16) % n;
  1464. }
  1465.  
  1466.     
  1467. //****************************************************************
  1468. // This function allows fetching of a random number
  1469.  
  1470. function getLibraryPlaylist( playlistname )
  1471. {
  1472.     var collection = player.playlistCollection.getAll();
  1473.     for (var nIndex = 0; nIndex < collection.count; nIndex++)
  1474.     {
  1475.         if (collection.item(nIndex).name == playlistname)
  1476.         {
  1477.             return collection.item(nIndex);
  1478.         }
  1479.     }
  1480.     return null;
  1481. }
  1482.  
  1483.  
  1484. //****************************************************************
  1485. // This function assures that indexes pointing to an old playlist
  1486. // collection are valid in a new playlsit collection
  1487.  
  1488. function reconcilePlaylistArray( oldCollection, newCollection, verify_array )
  1489. {
  1490.     for (var nIndex = 0; nIndex < verify_array.length; nIndex++)
  1491.     {
  1492.         var found   = false;
  1493.         var name    = oldCollection.item( verify_array[nIndex] ).name;
  1494.         
  1495.         for (var nInner = 0; nInner < newCollection.count; nInner++)
  1496.         {
  1497.             if (name == newCollection.item( nInner ).name)
  1498.             {
  1499.                 found = true;
  1500.                 verify_array[nIndex] = nInner;            
  1501.                 break;
  1502.             }
  1503.         }
  1504.         
  1505.         if (!found)
  1506.         {
  1507.             // If we didn't find it, then we need to remove it
  1508.             // from the array        
  1509.         
  1510.             var nInner = nIndex + 1;
  1511.             while (nInner < verify_array.length)
  1512.             {
  1513.                 verify_array[nInner - 1] = verify_array[nInner];
  1514.                 nInner++;
  1515.             }
  1516.             verify_array.length = verify_array.length - 1;
  1517.             
  1518.             nIndex--;
  1519.         }    
  1520.     }
  1521. }
  1522.  
  1523.