diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9041997e..f06c2415 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -172,6 +172,8 @@ THE SOFTWARE. android:name="TabOrderActivity" /> + list = sCallbacks; diff --git a/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java b/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java index 61005fe2..c1f78b11 100644 --- a/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java +++ b/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java @@ -72,10 +72,14 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba * Handler thread used to perform playlist sync. */ private Handler mHandler; + /** + * Observer which watches the playlist directory. + */ + private FileObserver mFileObserver; /** * Directory which holds observed playlists. */ - private File mPlaylists = new File(Environment.getExternalStorageDirectory(), "Playlists"); + private File mPlaylists; /** * What kind of synching to perform, bitmask of PlaylistObserver.SYNC_MODE_* */ @@ -96,10 +100,11 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba } - public PlaylistObserver(Context context, int mode) { + public PlaylistObserver(Context context, String folder, int mode) { super(context, "playlist_observer.db", null, 1 /* version */); mContext = context; - setSyncMode(mode); + mSyncMode = mode; + mPlaylists = new File(folder); // Launch new thread for background execution mHandlerThread= new HandlerThread("PlaylisObserverHandler", Process.THREAD_PRIORITY_LOWEST); @@ -108,6 +113,8 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba // Register to receive media library events. MediaLibrary.registerLibraryObserver(mLibraryObserver); + // Create and start directory observer. + mFileObserver = getFileObserver(mPlaylists); mFileObserver.startWatching(); XT("Object created, trigger FULL_SYNC_SCAN"); @@ -127,16 +134,6 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba mHandler = null; } - /** - * Change the sync mode of a created instance - * - * @param mode the new mode - */ - public void setSyncMode(int mode) { - mSyncMode = mode; - XT("Sync mode is now "+mSyncMode); - } - /** * SQLiteHelper onCreate */ @@ -561,25 +558,29 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba * @param event the event type * @param dirent the filename which triggered the event. */ - private final static int mask = FileObserver.CLOSE_WRITE | FileObserver.MOVED_FROM | FileObserver.MOVED_TO | FileObserver.DELETE; - private final FileObserver mFileObserver = new FileObserver(mPlaylists.getAbsolutePath(), mask) { - @Override - public void onEvent(int event, String dirent) { - if (!isM3uFilename(dirent)) - return; + private FileObserver getFileObserver(File target) { + final int mask = FileObserver.CLOSE_WRITE | FileObserver.MOVED_FROM | FileObserver.MOVED_TO | FileObserver.DELETE; + XT("new file observer at "+target+" with mask "+mask); - if ((event & (FileObserver.MOVED_FROM | FileObserver.DELETE)) != 0) { - // A M3U vanished, do a full scan. - XT("FileObserver::onEvent DELETE of "+dirent+" triggers FULL_SYNC_SCAN"); - sendUniqueMessage(MSG_FULL_SYNC_SCAN, 0); + return new FileObserver(target.getAbsolutePath(), mask) { + @Override + public void onEvent(int event, String dirent) { + if (!isM3uFilename(dirent)) + return; + + if ((event & (FileObserver.MOVED_FROM | FileObserver.DELETE)) != 0) { + // A M3U vanished, do a full scan. + XT("FileObserver::onEvent DELETE of "+dirent+" triggers FULL_SYNC_SCAN"); + sendUniqueMessage(MSG_FULL_SYNC_SCAN, 0); + } + if ((event & (FileObserver.MOVED_TO | FileObserver.CLOSE_WRITE)) != 0) { + // Single file was created, import it. + XT("FileObserver::onEvent WRITE of "+dirent+" triggers IMPORT_M3U"); + sendUniqueMessage(MSG_IMPORT_M3U, new File(mPlaylists, dirent)); + } } - if ((event & (FileObserver.MOVED_TO | FileObserver.CLOSE_WRITE)) != 0) { - // Single file was created, import it. - XT("FileObserver::onEvent WRITE of "+dirent+" triggers IMPORT_M3U"); - sendUniqueMessage(MSG_IMPORT_M3U, new File(mPlaylists, dirent)); - } - } - }; + }; + } private void XT(String s) { try(PrintWriter pw = new PrintWriter(new FileOutputStream(new File("/sdcard/playlist-observer.txt"), true))) { diff --git a/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserverDirActivity.java b/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserverDirActivity.java new file mode 100644 index 00000000..9d963d05 --- /dev/null +++ b/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserverDirActivity.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 Adrian Ulrich + * + * 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 . + */ + +package ch.blinkenlights.android.vanilla; + +import android.app.Activity; +import android.os.Bundle; +import android.content.SharedPreferences; + +import java.io.File; +import java.util.ArrayList; + +public class PlaylistObserverDirActivity extends FolderPickerActivity { + /** + * Shared preferences + */ + private SharedPreferences mPrefs; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTitle(R.string.filebrowser_start); + + mPrefs = PlaybackService.getSettings(this); + + // Start at currently configured directory. + String current = mPrefs.getString(PrefKeys.PLAYLIST_SYNC_FOLDER, PrefDefaults.PLAYLIST_SYNC_FOLDER); + setCurrentDir(new File(current)); + } + + + @Override + public void onFolderPicked(File directory, ArrayList a, ArrayList b) { + SharedPreferences.Editor editor = mPrefs.edit(); + editor.putString(PrefKeys.PLAYLIST_SYNC_FOLDER, directory.getAbsolutePath()); + editor.commit(); + finish(); + } + +} diff --git a/app/src/main/java/ch/blinkenlights/android/vanilla/PrefDefaults.java b/app/src/main/java/ch/blinkenlights/android/vanilla/PrefDefaults.java index db3cd18c..6bd82ab0 100644 --- a/app/src/main/java/ch/blinkenlights/android/vanilla/PrefDefaults.java +++ b/app/src/main/java/ch/blinkenlights/android/vanilla/PrefDefaults.java @@ -71,4 +71,5 @@ public class PrefDefaults { public static final boolean ENABLE_SCROLL_TO_SONG = false; public static final boolean KEEP_SCREEN_ON = false; public static final String PLAYLIST_SYNC_MODE = "255"; + public static final String PLAYLIST_SYNC_FOLDER = "/sdcard/Playlists"; } diff --git a/app/src/main/java/ch/blinkenlights/android/vanilla/PrefKeys.java b/app/src/main/java/ch/blinkenlights/android/vanilla/PrefKeys.java index e9f9ad46..7ee2e9ab 100644 --- a/app/src/main/java/ch/blinkenlights/android/vanilla/PrefKeys.java +++ b/app/src/main/java/ch/blinkenlights/android/vanilla/PrefKeys.java @@ -72,4 +72,5 @@ public class PrefKeys { public static final String ENABLE_SCROLL_TO_SONG = "enable_scroll_to_song"; public static final String KEEP_SCREEN_ON = "keep_screen_on"; public static final String PLAYLIST_SYNC_MODE = "playlist_sync_mode"; + public static final String PLAYLIST_SYNC_FOLDER = "playlist_sync_folder"; } diff --git a/app/src/main/java/ch/blinkenlights/android/vanilla/PreferencesActivity.java b/app/src/main/java/ch/blinkenlights/android/vanilla/PreferencesActivity.java index cf1cc6f7..4193ffef 100644 --- a/app/src/main/java/ch/blinkenlights/android/vanilla/PreferencesActivity.java +++ b/app/src/main/java/ch/blinkenlights/android/vanilla/PreferencesActivity.java @@ -239,6 +239,15 @@ public class PreferencesActivity extends PreferenceActivity } } + public static class PlaylistFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preference_playlist); + } + } + public static class HelpFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) diff --git a/app/src/main/res/values/translatable.xml b/app/src/main/res/values/translatable.xml index a24b11ca..9c93afdd 100644 --- a/app/src/main/res/values/translatable.xml +++ b/app/src/main/res/values/translatable.xml @@ -331,10 +331,12 @@ THE SOFTWARE. Top %d Playlist synchronization - Synchronize \'Playlists\' folder + Full synchronization Import M3U, never export Write M3U, never import Disabled + Synchronization folder + Folder to use for playlist synchronization Vanilla Music needs read permission to display your music library Reverse sort diff --git a/app/src/main/res/xml/preference_headers.xml b/app/src/main/res/xml/preference_headers.xml index 84c0d0f4..66cffd1b 100644 --- a/app/src/main/res/xml/preference_headers.xml +++ b/app/src/main/res/xml/preference_headers.xml @@ -45,6 +45,9 @@ THE SOFTWARE.
+
diff --git a/app/src/main/res/xml/preference_misc.xml b/app/src/main/res/xml/preference_misc.xml index 1f6d1022..7c4883df 100644 --- a/app/src/main/res/xml/preference_misc.xml +++ b/app/src/main/res/xml/preference_misc.xml @@ -49,23 +49,6 @@ THE SOFTWARE. android:title="@string/double_tap_title" android:summary="@string/double_tap_summary" android:defaultValue="false" /> - - + + + + + + + +