2 * Copyright (C) 2014 The CyanogenMod Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.cyanogenmod.eleven.provider;
18 import android.content.ContentValues;
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.database.sqlite.SQLiteDatabase;
23 import com.cyanogenmod.eleven.utils.MusicUtils;
26 * This db stores the details to generate the playlist artwork including when it was
27 * last updated and the # of songs in the playlist when it last updated
29 public class PlaylistArtworkStore {
30 private static final long ONE_DAY_IN_MS = 1000 * 60 * 60 * 24;
32 private static PlaylistArtworkStore sInstance = null;
34 private MusicDB mMusicDatabase = null;
37 * @param context The {@link android.content.Context} to use
38 * @return A new instance of this class.
40 public static final synchronized PlaylistArtworkStore getInstance(final Context context) {
41 if (sInstance == null) {
42 sInstance = new PlaylistArtworkStore(context.getApplicationContext());
48 * @param playlistId playlist identifier
49 * @return the key used for the imagae cache for the cover art
51 public static final String getCoverCacheKey(final long playlistId) {
52 return "playlist_cover_" + playlistId;
56 * @param playlistId playlist identifier
57 * @return the key used for the imagae cache for the top artist image
59 public static final String getArtistCacheKey(final long playlistId) {
60 return "playlist_artist_" + playlistId;
63 private final Context mContext;
66 * Constructor of <code>RecentStore</code>
68 * @param context The {@link android.content.Context} to use
70 public PlaylistArtworkStore(final Context context) {
71 mMusicDatabase = MusicDB.getInstance(context);
76 public void onCreate(final SQLiteDatabase db) {
78 String builder = "CREATE TABLE IF NOT EXISTS " +
79 PlaylistArtworkStoreColumns.NAME +
81 PlaylistArtworkStoreColumns.ID +
83 PlaylistArtworkStoreColumns.LAST_UPDATE_ARTIST +
85 PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_ARTIST +
87 PlaylistArtworkStoreColumns.LAST_UPDATE_COVER +
89 PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_COVER +
95 public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
96 // No upgrade path needed yet
99 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
100 // If we ever have downgrade, drop the table to be safe
101 db.execSQL("DROP TABLE IF EXISTS " + PlaylistArtworkStoreColumns.NAME);
106 * @param playlistId playlist identifier
107 * @return true if the artist artwork should be updated based on time since last update and
108 * whether the # of songs for the playlist has changed
110 public boolean needsArtistArtUpdate(final long playlistId) {
111 return needsUpdate(playlistId, PlaylistArtworkStoreColumns.LAST_UPDATE_ARTIST,
112 PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_ARTIST);
116 * @param playlistId playlist identifier
117 * @return true if the cover artwork should be updated based on time since last update and
118 * whether the # of songs for the playlist has changed
120 public boolean needsCoverArtUpdate(final long playlistId) {
121 return needsUpdate(playlistId, PlaylistArtworkStoreColumns.LAST_UPDATE_COVER,
122 PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_COVER);
126 * Updates the time and the # of songs in the db for the artist section of the table
127 * @param playlistId playlist identifier
129 public void updateArtistArt(final long playlistId) {
130 updateOrInsertTime(playlistId, PlaylistArtworkStoreColumns.LAST_UPDATE_ARTIST,
131 PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_ARTIST);
135 * Updates the time and the # of songs in the db for the cover art of the table
136 * @param playlistId playlist identifier
138 public void updateCoverArt(final long playlistId) {
139 updateOrInsertTime(playlistId, PlaylistArtworkStoreColumns.LAST_UPDATE_COVER,
140 PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_COVER);
144 * Internal function to update the entry for the columns passed in
145 * @param playlistId playlist identifier
146 * @param columnName the column to update to the current time
147 * @param countColumnName the column to set the # of songs to based on the playlist
149 private void updateOrInsertTime(final long playlistId, final String columnName, final String countColumnName) {
150 SQLiteDatabase database = mMusicDatabase.getWritableDatabase();
152 database.beginTransaction();
154 // gets the existing values for the entry if it exists
155 ContentValues values = getExistingContentValues(playlistId);
156 boolean existingEntry = values.size() > 0;
158 values.put(PlaylistArtworkStoreColumns.ID, playlistId);
159 values.put(columnName, System.currentTimeMillis());
160 values.put(countColumnName, MusicUtils.getSongCountForPlaylist(mContext, playlistId));
162 // if it is an existing entry, update, otherwise insert
164 database.update(PlaylistArtworkStoreColumns.NAME, values,
165 PlaylistArtworkStoreColumns.ID + "=" + playlistId, null);
167 database.insert(PlaylistArtworkStoreColumns.NAME, null, values);
170 database.setTransactionSuccessful();
171 database.endTransaction();
175 * Internal function to get the existing values for a playlist entry
176 * @param playlistId playlist identifier
177 * @return the content values
179 private ContentValues getExistingContentValues(final long playlistId) {
180 ContentValues values = new ContentValues(4);
181 Cursor c = getEntry(playlistId);
182 if (c != null && c.moveToFirst()) {
183 values.put(PlaylistArtworkStoreColumns.ID, c.getLong(0));
184 values.put(PlaylistArtworkStoreColumns.LAST_UPDATE_ARTIST, c.getLong(1));
185 values.put(PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_ARTIST, c.getInt(2));
186 values.put(PlaylistArtworkStoreColumns.LAST_UPDATE_COVER, c.getLong(3));
187 values.put(PlaylistArtworkStoreColumns.NUM_SONGS_LAST_UPDATE_COVER, c.getInt(4));
196 * Internal function to return whether the columns show that this needs an update
197 * @param playlistId playlist identifier
198 * @param columnName the column to inspect
199 * @param countColumnName the column count to inspect
202 private boolean needsUpdate(final long playlistId, final String columnName, final String countColumnName) {
204 Cursor c = getEntry(playlistId);
206 if (c != null && c.moveToFirst()) {
207 final long lastUpdate = c.getLong(c.getColumnIndex(columnName));
208 final long msSinceEpoch = System.currentTimeMillis();
209 final int songCount = MusicUtils.getSongCountForPlaylist(mContext, playlistId);
210 final int lastUpdatedSongCount = c.getInt(c.getColumnIndex(countColumnName));
215 // if the elapsed time since our last update is less than a day and the
216 // number of songs in the playlist hasn't changed, then don't update
217 if (msSinceEpoch - lastUpdate < ONE_DAY_IN_MS &&
218 songCount == lastUpdatedSongCount) {
227 * Internal function to get the cursor entry for the playlist
228 * @param playlistId playlist identifier
231 private Cursor getEntry(final long playlistId) {
232 SQLiteDatabase db = mMusicDatabase.getReadableDatabase();
233 return db.query(PlaylistArtworkStoreColumns.NAME, null,
234 PlaylistArtworkStoreColumns.ID + "=" + playlistId, null, null, null, null);
237 public interface PlaylistArtworkStoreColumns {
239 public static final String NAME = "playlist_details";
241 /* Playlist ID column */
242 public static final String ID = "playlistid";
244 /* When the top artist was last updated */
245 public static final String LAST_UPDATE_ARTIST = "last_updated_artist";
247 /* The number of songs when we last updated the artist */
248 public static final String NUM_SONGS_LAST_UPDATE_ARTIST = "num_songs_last_updated_artist";
250 /* When the cover art was last updated */
251 public static final String LAST_UPDATE_COVER = "last_updated_cover";
253 /* The number of songs when we last updated the cover */
254 public static final String NUM_SONGS_LAST_UPDATE_COVER = "num_songs_last_updated_cover";