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" />
-
-
+
+
+
+
+
+
+
+