View Javadoc

1   /***
2    *     Ambient - A music player for the Android platform
3    Copyright (C) 2007 Martin Vysny
4    
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9    
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14  
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  package sk.baka.ambient.playlist;
19  
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.Map;
24  
25  /***
26   * Random play.
27   * 
28   * @author Martin Vysny
29   */
30  public enum Random {
31  	/***
32  	 * No random play, tracks will be played as ordered by the playlist.
33  	 */
34  	NONE(false),
35  	/***
36  	 * 
37  	 */
38  	TRACK(false),
39  	/***
40  	 * A random album is selected which is then played regularly (in album
41  	 * order).
42  	 */
43  	ALBUM(true),
44  	/***
45  	 * A random album is selected which is then played in the playlist order
46  	 * (order in which tracks appear in the playlist).
47  	 */
48  	ALBUM_PLAYLIST(true),
49  	/***
50  	 * A random album is selected and random tracks are played from it.
51  	 */
52  	ALBUM_TRACK(true);
53  	/***
54  	 * Randomizes given playlist as specified by the <code>Random</code>
55  	 * constant.
56  	 * 
57  	 * @param random
58  	 *            the random constant
59  	 * @param playlist
60  	 *            the playlist to randomize, will not be changed.
61  	 * @param first
62  	 *            place this track first if possible. May be <code>null</code>
63  	 *            if it doesn't matter which track is the first one.
64  	 * @return a new, shuffled list.
65  	 */
66  	public static List<PlaylistItem> randomize(final Random random,
67  			final List<? extends PlaylistItem> playlist,
68  			final PlaylistItem first) {
69  		// TODO vyzivus: rollback this class to the previous state when
70  		// http://code.google.com/p/android/issues/detail?id=220 is fixed
71  		switch (random) {
72  		case NONE:
73  			return new ArrayList<PlaylistItem>(playlist);
74  		case TRACK: {
75  			final List<PlaylistItem> result = new ArrayList<PlaylistItem>(
76  					playlist);
77  			Collections.shuffle(result);
78  			if (first != null) {
79  				final int indexOfFirst = result.indexOf(first);
80  				Collections.swap(result, 0, indexOfFirst);
81  			}
82  			return result;
83  		}
84  		case ALBUM:
85  		case ALBUM_PLAYLIST:
86  		case ALBUM_TRACK: {
87  			// first sort the playlist, so that we don't have to sort
88  			// tracks for each album
89  			final List<PlaylistItem> result = new ArrayList<PlaylistItem>(
90  					playlist);
91  			if (random == Random.ALBUM) {
92  				Utils.sortPlaylistByAlbumOrder(result);
93  			} else if (random == Random.ALBUM_TRACK) {
94  				Collections.shuffle(result);
95  			}
96  			// now create an album-tracks map - we are going to 'shuffle'
97  			// the map 'keys'
98  			final Map<String, List<PlaylistItem>> albums = Utils
99  					.getAlbumsFromPlaylist(result);
100 			// shuffle the album names
101 			final List<String> albumNames = new ArrayList<String>(albums
102 					.keySet());
103 			Collections.shuffle(albumNames);
104 			// move the album containing the 'first' track up
105 			if (first != null) {
106 				final int indexOfFirst = albumNames.indexOf(first.track
107 						.getAlbum());
108 				Collections.swap(albumNames, 0, indexOfFirst);
109 			}
110 			// finally, create the shuffled result list
111 			result.clear();
112 			for (final String albumName : albumNames) {
113 				result.addAll(albums.get(albumName));
114 			}
115 			return result;
116 		}
117 		}
118 		throw new Error();
119 	}
120 
121 	/***
122 	 * <code>true</code> if tracks are grouped by albums ({@link #ALBUM},
123 	 * {@link #ALBUM_PLAYLIST} and {@link #ALBUM_TRACK}) , <code>false</code>
124 	 * otherwise.
125 	 */
126 	private final boolean groupsByAlbum;
127 
128 	private Random(final boolean groupsByAlbum) {
129 		this.groupsByAlbum = groupsByAlbum;
130 	}
131 
132 	/***
133 	 * Checks if this random mode groups tracks by albums.
134 	 * 
135 	 * @return <code>true</code> if tracks are grouped by albums ({@link #ALBUM},
136 	 *         {@link #ALBUM_PLAYLIST} and {@link #ALBUM_TRACK}) ,
137 	 *         <code>false</code> otherwise.
138 	 */
139 	public final boolean groupsByAlbum() {
140 		return groupsByAlbum;
141 	}
142 }