introduce PlaylistObserver
This commit is contained in:
parent
d8b276d586
commit
eba6acabc2
@ -26,9 +26,8 @@ public class LibraryObserver {
|
||||
* by the receiver
|
||||
*/
|
||||
public enum Type {
|
||||
ANY, // Any type may have changed
|
||||
SONG, // Change only affected song entries
|
||||
PLAYLIST, // Change only affected playlists
|
||||
SONG, // Change affected song entries
|
||||
PLAYLIST, // Change affected playlists
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,9 +41,10 @@ public class LibraryObserver {
|
||||
* to be overriden by the registered observer.
|
||||
*
|
||||
* @param type one of LibraryObserver.Type
|
||||
* @param id hint of which id changed for type, -1 if unspecified.
|
||||
* @param ongoing whether or not to expect more events soon.
|
||||
*/
|
||||
public void onChange(Type type, boolean ongoing) {
|
||||
public void onChange(Type type, long id, boolean ongoing) {
|
||||
// NOOP, should be overriden.
|
||||
}
|
||||
}
|
||||
|
@ -324,11 +324,15 @@ public class MediaLibrary {
|
||||
|
||||
/**
|
||||
* Broadcasts a change to all registered observers
|
||||
*
|
||||
* @param type the type of this event.
|
||||
* @param id the id of type which changed, -1 if unknown
|
||||
* @param ongoing whether or not to expect more of these updates soon
|
||||
*/
|
||||
static void notifyObserver(LibraryObserver.Type type, boolean ongoing) {
|
||||
static void notifyObserver(LibraryObserver.Type type, long id, boolean ongoing) {
|
||||
ArrayList<LibraryObserver> list = sLibraryObservers;
|
||||
for (int i = list.size(); --i != -1; )
|
||||
list.get(i).onChange(type, ongoing);
|
||||
list.get(i).onChange(type, id, ongoing);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,7 +361,8 @@ public class MediaLibrary {
|
||||
|
||||
if (rows > 0) {
|
||||
getBackend(context).cleanOrphanedEntries(true);
|
||||
notifyObserver(LibraryObserver.Type.ANY, false);
|
||||
notifyObserver(LibraryObserver.Type.SONG, id, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, -1, false);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
@ -389,7 +394,7 @@ public class MediaLibrary {
|
||||
long id = getBackend(context).insert(MediaLibrary.TABLE_PLAYLISTS, null, v);
|
||||
|
||||
if (id != -1)
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, id, false);
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -407,7 +412,7 @@ public class MediaLibrary {
|
||||
boolean removed = (rows > 0);
|
||||
|
||||
if (removed)
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, id, false);
|
||||
return removed;
|
||||
}
|
||||
|
||||
@ -445,7 +450,7 @@ public class MediaLibrary {
|
||||
int rows = getBackend(context).bulkInsert(MediaLibrary.TABLE_PLAYLISTS_SONGS, null, bulk);
|
||||
|
||||
if (rows > 0)
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, playlistId, false);
|
||||
return rows;
|
||||
}
|
||||
|
||||
@ -461,7 +466,7 @@ public class MediaLibrary {
|
||||
int rows = getBackend(context).delete(MediaLibrary.TABLE_PLAYLISTS_SONGS, selection, selectionArgs);
|
||||
|
||||
if (rows > 0)
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, -1, false);
|
||||
return rows;
|
||||
}
|
||||
|
||||
@ -483,8 +488,10 @@ public class MediaLibrary {
|
||||
removePlaylist(context, playlistId);
|
||||
}
|
||||
|
||||
if (newId != -1)
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, false);
|
||||
if (newId != -1) {
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, playlistId, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, newId, false);
|
||||
}
|
||||
return newId;
|
||||
}
|
||||
|
||||
@ -529,7 +536,7 @@ public class MediaLibrary {
|
||||
selection = MediaLibrary.PlaylistSongColumns._ID+"="+from;
|
||||
getBackend(context).update(MediaLibrary.TABLE_PLAYLISTS_SONGS, v, selection, null);
|
||||
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, false);
|
||||
notifyObserver(LibraryObserver.Type.PLAYLIST, playlistId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,7 +205,7 @@ public class MediaScanner implements Handler.Callback {
|
||||
|
||||
switch (rpc) {
|
||||
case MSG_NOTIFY_CHANGE: {
|
||||
MediaLibrary.notifyObserver(LibraryObserver.Type.SONG, true);
|
||||
MediaLibrary.notifyObserver(LibraryObserver.Type.SONG, -1, true);
|
||||
break;
|
||||
}
|
||||
case MSG_SCAN_FINISHED: {
|
||||
@ -216,6 +216,8 @@ public class MediaScanner implements Handler.Callback {
|
||||
if (mPendingCleanup) {
|
||||
mPendingCleanup = false;
|
||||
mBackend.cleanOrphanedEntries(true);
|
||||
// scan run possibly deleted file which may affect playlists:
|
||||
MediaLibrary.notifyObserver(LibraryObserver.Type.PLAYLIST, -1, false);
|
||||
}
|
||||
|
||||
// Send a last change notification to all observers.
|
||||
@ -224,7 +226,7 @@ public class MediaScanner implements Handler.Callback {
|
||||
// also signals that this will be our last update
|
||||
// for this scan.
|
||||
mHandler.removeMessages(MSG_NOTIFY_CHANGE);
|
||||
MediaLibrary.notifyObserver(LibraryObserver.Type.ANY, false);
|
||||
MediaLibrary.notifyObserver(LibraryObserver.Type.SONG, -1, false);
|
||||
|
||||
updateNotification(false);
|
||||
break;
|
||||
|
@ -431,6 +431,10 @@ public final class PlaybackService extends Service
|
||||
* Reference to precreated ReadAhead thread
|
||||
*/
|
||||
private ReadaheadThread mReadahead;
|
||||
/**
|
||||
* Referente to our playlist observer
|
||||
*/
|
||||
private PlaylistObserver mPlaylistObserver;
|
||||
/**
|
||||
* Reference to precreated BASTP Object
|
||||
*/
|
||||
@ -502,6 +506,8 @@ public final class PlaybackService extends Service
|
||||
mRemoteControlClient = new RemoteControl().getClient(this);
|
||||
mRemoteControlClient.initializeRemote();
|
||||
|
||||
mPlaylistObserver = new PlaylistObserver();
|
||||
|
||||
mLooper = thread.getLooper();
|
||||
mHandler = new Handler(mLooper, this);
|
||||
|
||||
@ -616,6 +622,7 @@ public final class PlaybackService extends Service
|
||||
enterSleepState();
|
||||
|
||||
MediaLibrary.unregisterLibraryObserver(mObserver);
|
||||
mPlaylistObserver.unregister();
|
||||
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.release();
|
||||
@ -1932,7 +1939,7 @@ public final class PlaybackService extends Service
|
||||
|
||||
private final LibraryObserver mObserver = new LibraryObserver() {
|
||||
@Override
|
||||
public void onChange(LibraryObserver.Type type, boolean ongoing)
|
||||
public void onChange(LibraryObserver.Type type, long id, boolean ongoing)
|
||||
{
|
||||
MediaUtils.onMediaChange();
|
||||
onMediaChange();
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Adrian Ulrich <adrian@blinkenlights.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ch.blinkenlights.android.vanilla;
|
||||
|
||||
import ch.blinkenlights.android.medialibrary.MediaLibrary;
|
||||
import ch.blinkenlights.android.medialibrary.LibraryObserver;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
|
||||
import java.io.File;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
public class PlaylistObserver implements Handler.Callback {
|
||||
/**
|
||||
* Handler thread used to perform playlist sync.
|
||||
*/
|
||||
private Handler mHandler;
|
||||
/**
|
||||
* Directory which holds observed playlists.
|
||||
*/
|
||||
private File mPlaylists = new File(Environment.getExternalStorageDirectory(), "Playlists");
|
||||
|
||||
|
||||
public PlaylistObserver() {
|
||||
// Create thread which will be used for background work.
|
||||
HandlerThread handlerThread = new HandlerThread("PlaylistWriter", Process.THREAD_PRIORITY_LOWEST);
|
||||
handlerThread.start();
|
||||
mHandler = new Handler(handlerThread.getLooper(), this);
|
||||
// Register to receive media library events.
|
||||
MediaLibrary.registerLibraryObserver(mObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this observer, the object must not be used anymore
|
||||
* after this function was called.
|
||||
*/
|
||||
public void unregister() {
|
||||
MediaLibrary.unregisterLibraryObserver(mObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Library observer callback which notifies us about media library
|
||||
* events.
|
||||
*/
|
||||
private final LibraryObserver mObserver = new LibraryObserver() {
|
||||
@Override
|
||||
public void onChange(LibraryObserver.Type type, long id, boolean ongoing) {
|
||||
Log.v("VanillaMusic", "onChange type = "+type+", id = "+id+" ongoing = "+ongoing);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO:
|
||||
// Use FileObserver to track playlist changes?
|
||||
// how do we check modifications? write a shadow-dir in private app storage with same mtimes?
|
||||
}
|
@ -133,7 +133,7 @@ public class ScheduledLibraryUpdate extends JobService {
|
||||
*/
|
||||
private final LibraryObserver mObserver = new LibraryObserver() {
|
||||
@Override
|
||||
public void onChange(LibraryObserver.Type type, boolean ongoing) {
|
||||
public void onChange(LibraryObserver.Type type, long id, boolean ongoing) {
|
||||
if (!ongoing) {
|
||||
jobFinished(mJobParams, false);
|
||||
finalizeScan();
|
||||
|
Loading…
x
Reference in New Issue
Block a user